DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/3] eal: Add new API for threading
@ 2021-03-18  1:00 Narcisa Ana Maria Vasile
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
                   ` (2 more replies)
  0 siblings, 3 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-18  1:00 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread API. Given that EAL should isolate the environment
specifics from the applications and libraries and intermediate
the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  rte_thread_* API.
* Allow users to choose between using the rte_thread_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the rte_thread_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the rte_thread_* API for managing threads.

If compiling on Windows and the new EAL API will be used,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application. The two options above are available:

 --thread-prio normal
 --thread-prio realtime
 
Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue using them,
  they need to be platform dependent and an implementation will need to be provided for Windows.

Narcisa Vasile (3):
  Add EAL threads API
  Add EAL argument for setting thread priority
  Enable the new EAL thread API and rename

 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   4 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   4 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  54 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  54 +-
 examples/kni/main.c                           |   4 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |  32 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 +-
 lib/librte_eal/common/eal_common_thread.c     |  47 +-
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_internal_cfg.h      |   2 +
 lib/librte_eal/common/eal_options.h           |   2 +
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +-
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/common/rte_thread.c            | 346 ++++++++++++
 lib/librte_eal/freebsd/eal.c                  |  33 +-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/include/rte_thread.h           | 323 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/linux/eal.c                    |  36 +-
 lib/librte_eal/linux/eal_alarm.c              |   8 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  19 +
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  86 ---
 lib/librte_eal/version.map                    |  21 +
 lib/librte_eal/windows/eal.c                  |  24 +-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_lcore.c            | 167 ++++--
 lib/librte_eal/windows/eal_thread.c           |  24 +-
 lib/librte_eal/windows/eal_windows.h          |  20 +-
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 -------
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_eal/windows/rte_thread.c           | 507 +++++++++++++++++-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 +-
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++---
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 107 files changed, 2001 insertions(+), 899 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH 1/3] Add EAL threads API
  2021-03-18  1:00 [dpdk-dev] [PATCH 0/3] eal: Add new API for threading Narcisa Ana Maria Vasile
@ 2021-03-18  1:00 ` Narcisa Ana Maria Vasile
  2021-03-18 14:48   ` Tal Shnaiderman
                     ` (2 more replies)
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 2/3] Add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 3/3] Enable the new EAL thread API and rename Narcisa Ana Maria Vasile
  2 siblings, 3 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-18  1:00 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL must hide the environment specifics from apps and libraries.
Add an EAL API for managing threads.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/librte_eal/common/eal_common_thread.c     |   6 +-
 lib/librte_eal/common/rte_thread.c            | 346 ++++++++++++
 lib/librte_eal/include/rte_thread.h           | 323 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/windows/eal_lcore.c            | 167 ++++--
 lib/librte_eal/windows/eal_windows.h          |  10 +
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/rte_thread.c           | 507 +++++++++++++++++-
 8 files changed, 1338 insertions(+), 60 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 73a055902..5219e783e 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -84,7 +84,7 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 }
 
 int
-rte_thread_set_affinity(rte_cpuset_t *cpusetp)
+rte_thread_self_set_affinity(rte_cpuset_t *cpusetp)
 {
 	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
 			cpusetp) != 0) {
@@ -97,7 +97,7 @@ rte_thread_set_affinity(rte_cpuset_t *cpusetp)
 }
 
 void
-rte_thread_get_affinity(rte_cpuset_t *cpusetp)
+rte_thread_self_get_affinity(rte_cpuset_t *cpusetp)
 {
 	assert(cpusetp);
 	memmove(cpusetp, &RTE_PER_LCORE(_cpuset),
@@ -140,7 +140,7 @@ eal_thread_dump_current_affinity(char *str, unsigned int size)
 {
 	rte_cpuset_t cpuset;
 
-	rte_thread_get_affinity(&cpuset);
+	rte_thread_self_get_affinity(&cpuset);
 	return eal_thread_dump_affinity(&cpuset, str, size);
 }
 
diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
new file mode 100644
index 000000000..275876534
--- /dev/null
+++ b/lib/librte_eal/common/rte_thread.c
@@ -0,0 +1,346 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return pthread_self();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1, t2);
+}
+
+int
+rte_thread_set_affinity(rte_thread_t thread_id, size_t cpuset_size,
+			const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id, cpuset_size, cpuset);
+}
+
+int rte_thread_get_affinity(rte_thread_t threadid, size_t cpuset_size,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int policy;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+
+
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+		policy = SCHED_RR;
+		param.sched_priority = priority;
+	} else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+		policy = SCHED_OTHER;
+		param.sched_priority = priority;
+	} else {
+		RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+				    "Defaulting to priority 'normal'.\n");
+		policy = SCHED_OTHER;
+	}
+
+	return pthread_setschedparam(thread_id, policy, &param);
+}
+
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	int ret = 0;
+	pthread_attr_t pthread_attr;
+
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return -EINVAL;
+	}
+
+	ret = pthread_getattr_default_np(&pthread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_getattr_default_np failed\n");
+		return ret;
+	}
+
+	ret = pthread_attr_getaffinity_np(&pthread_attr, sizeof(attr->cpuset), &attr->cpuset);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_attr_getaffinity_np failed\n");
+		return ret;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return -EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return -EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr, enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return -EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr, void *(*thread_func) (void*),
+		  void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/* Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp, PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/* In case a realtime scheduling policy is requested, the sched_priority
+		 * parameter is set to the value stored in thread_attr. Otherwise, for
+		 * the default scheduling policy (SCHED_OTHER) sched_priority needs to
+		 * be intialized to 0. */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp, sizeof(thread_attr->cpuset), &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(thread_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL) {
+		pthread_attr_destroy(&attr);
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL) {
+		pres = &res;
+	}
+
+	ret = pthread_join(thread_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL) {
+		*value_ptr = *(int*)(*pres);
+	}
+	return 0;
+}
+
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	return pthread_barrier_init(barrier, NULL, count);
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_wait(barrier);
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_destroy(barrier);
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id);
+}
+
+int
+rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
+{
+	int err;
+
+	*key = malloc(sizeof(**key));
+	if ((*key) == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return -EINVAL;
+	}
+	err = pthread_key_create(&((*key)->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(*key);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+int
+rte_thread_tls_key_delete(rte_tls_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return -EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return -EINVAL;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_tls_value_set(rte_tls_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return -EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void *
+rte_thread_tls_value_get(rte_tls_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index e640ea185..66b112bc4 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -20,11 +20,330 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
+enum rte_thread_priority
+{
+	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,
+	/*
+	 * This enum can be extended to allow more priority levels.
+	 */
+};
+
+typedef struct
+{
+	enum rte_thread_priority priority;
+	rte_cpuset_t cpuset;
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_tls_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset_size
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_set_affinity(rte_thread_t thread_id, size_t cpuset_size,
+			    const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset_size
+ *    Size of the cpu set.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_get_affinity(rte_thread_t thread_id, size_t cpuset_size,
+			    rte_cpuset_t *cpuset);
+
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id, enum rte_thread_priority priority);
+
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr;
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr, enum rte_thread_priority priority);
+
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func) (void*), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @param attr
+ *    Attributes for initialization of the mutex.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized at the barrier.
+ *   Return 0 for all other threads.
+ *   Return error number in case of error.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return an error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be terminated.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return nonzero.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
@@ -34,7 +353,7 @@ typedef struct eal_tls_key *rte_tls_key;
  * @return
  *   On success, return 0; otherwise return -1;
  */
-int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+int rte_thread_self_set_affinity(rte_cpuset_t *cpusetp);
 
 /**
  * Get core affinity of the current thread.
@@ -44,7 +363,7 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  *   It presumes input is not NULL, otherwise it causes panic.
  *
  */
-void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+void rte_thread_self_get_affinity(rte_cpuset_t *cpusetp);
 
 /**
  * Create a TLS data key visible to all threads in the process.
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
new file mode 100644
index 000000000..b055bbf67
--- /dev/null
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
+typedef pthread_t                       rte_thread_t;
+typedef pthread_mutex_t                 rte_thread_mutex_t;
+typedef pthread_barrier_t               rte_thread_barrier_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
index a85149be9..3e63f9f70 100644
--- a/lib/librte_eal/windows/eal_lcore.c
+++ b/lib/librte_eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -28,10 +27,12 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
 static struct cpu_map cpu_map = { 0 };
@@ -48,13 +49,110 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL, &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, error %lu\n",
+				  error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos, &infos_size)) {
+		log_early("Cannot get group information, error %lu\n", GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets)) {
+			return true;
+		}
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
+			return true;
+		}
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -79,57 +177,27 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
-		}
+		if (eal_check_for_duplicate_numa(info))
+			break;
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -139,7 +207,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -165,3 +233,12 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	if (cpu_index < CPU_SETSIZE)
+		return &cpu_map.cpus[cpu_index];
+
+	return NULL;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index 478accc1b..dc5dc8240 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 000000000..b6209e6eb
--- /dev/null
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
+
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
+typedef DWORD                       rte_thread_t;
+typedef CRITICAL_SECTION            rte_thread_mutex_t;
+typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 2e2ab2917..decb4b24d 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -1,16 +1,503 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
-#include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int rte_thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return -EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return -EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return -ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return -EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return -EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return -EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return -ENOSYS;
+
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1 == t2 ? 1 : 0;
+}
+
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = -EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int rte_thread_set_affinity(rte_thread_t thread_id,
+			    size_t cpuset_size,
+			    const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity(rte_thread_t thread_id, size_t cpuset_size,
+			rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id, enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	DWORD priority_class = NORMAL_PRIORITY_CLASS;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	switch (priority) {
+
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		priority_class = REALTIME_PRIORITY_CLASS;
+		break;
+
+	case RTE_THREAD_PRIORITY_NORMAL:
+	/* FALLTHROUGH */
+	default:
+		priority_class = NORMAL_PRIORITY_CLASS;
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+		break;
+	}
+
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, priority)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to init thread attributes, invalid parameter\n");
+		return -EINVAL;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set affinity attribute, invalid parameter\n");
+		return -EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set affinity attribute, invalid parameter\n");
+		return -EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr, enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return -EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr, void *(*thread_func) (void*),
+		  void *args)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+
+	thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, args, 0, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("CreateThread()");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = rte_thread_translate_win32_error(GetLastError());
+				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = rte_thread_translate_win32_error(GetLastError());
+			RTE_LOG_WIN32_ERR("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+
+	if (!InitializeSynchronizationBarrier(barrier, count, -1)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("InitializeSynchronizationBarrier()");
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return EnterSynchronizationBarrier(barrier,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	DeleteSynchronizationBarrier(barrier);
+	return 0;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
@@ -18,13 +505,13 @@ rte_thread_tls_key_create(rte_tls_key *key,
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		return -1;
+		return -ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
 		RTE_LOG_WIN32_ERR("TlsAlloc()");
 		free(*key);
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());;
 	}
 	return 0;
 }
@@ -32,14 +519,14 @@ rte_thread_tls_key_create(rte_tls_key *key,
 int
 rte_thread_tls_key_delete(rte_tls_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
+		return -EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
 		RTE_LOG_WIN32_ERR("TlsFree()");
 		free(key);
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	free(key);
 	return 0;
@@ -50,7 +537,7 @@ rte_thread_tls_value_set(rte_tls_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		return -1;
 	}
@@ -58,7 +545,7 @@ rte_thread_tls_value_set(rte_tls_key key, const void *value)
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
 		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -68,7 +555,7 @@ rte_thread_tls_value_get(rte_tls_key key)
 {
 	void *output;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH 2/3] Add EAL argument for setting thread priority
  2021-03-18  1:00 [dpdk-dev] [PATCH 0/3] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
@ 2021-03-18  1:00 ` Narcisa Ana Maria Vasile
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 3/3] Enable the new EAL thread API and rename Narcisa Ana Maria Vasile
  2 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-18  1:00 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

This patch introduces a new EAL argument that allows
the user to choose the desired thread priority (realtime or normal).

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/eal_common_options.c | 28 +++++++++++++++++++++-
 lib/librte_eal/common/eal_internal_cfg.h   |  2 ++
 lib/librte_eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 622c7bc42..287a89a75 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -106,6 +106,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1383,6 +1384,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1796,7 +1815,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2059,6 +2084,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 51dbe86e2..7ab1d0008 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -93,6 +93,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 7b348e707..9f5b209f6 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH 3/3] Enable the new EAL thread API and rename
  2021-03-18  1:00 [dpdk-dev] [PATCH 0/3] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 2/3] Add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-18  1:00 ` Narcisa Ana Maria Vasile
  2 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-18  1:00 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Enable the new EAL API in the build system.
Enable the new EAL argument for choosing priority.
Remove the pthread.h Windows shim.
Rename instances of pthread_* with the new rte_thread_* API.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   4 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   4 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +--
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  54 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 ++--
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  54 +++--
 examples/kni/main.c                           |   4 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |   4 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 ++---
 lib/librte_eal/common/eal_common_thread.c     |  41 ++--
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +--
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/freebsd/eal.c                  |  33 +++-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/linux/eal.c                    |  36 +++-
 lib/librte_eal/linux/eal_alarm.c              |   8 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  19 ++
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  86 --------
 lib/librte_eal/version.map                    |  21 ++
 lib/librte_eal/windows/eal.c                  |  24 ++-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_thread.c           |  24 +--
 lib/librte_eal/windows/eal_windows.h          |  10 -
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------------------
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 ++--
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++++++------
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 99 files changed, 632 insertions(+), 838 deletions(-)
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index 27f1b1c0e..ff284335a 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 #endif
 #endif
 
@@ -127,7 +127,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
-		pthread_create(&thread, NULL, &send_pkts, NULL);
+		rte_thread_create(&thread, NULL, &send_pkts, NULL);
 #endif
 #endif
 
@@ -137,7 +137,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fc..c507e423e 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a..3d9663f5e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d06..ce79d9c17 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 3cf560b8a..990fe6681 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -255,6 +255,10 @@ else # for 32-bit we need smaller reserved memory areas
 	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index 750b756b9..390770401 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -37,10 +37,10 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
+	ret = rte_thread_get_affinity(rte_thread_self(), sizeof(cpu_set_t),
 				     &cpuset);
 	if (ret) {
-		error(0, ret, "pthread_getaffinity_np()");
+		error(0, ret, "rte_thread_get_affinity()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a..dc5f02bec 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681c..6d2d10cdf 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1..731916ab9 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -92,10 +92,10 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
+	ret = rte_thread_get_affinity(rte_thread_self(), sizeof(cpu_set_t),
 		&cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity() failed");
 		return ret;
 	}
 
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index 46255ab5e..43af76ec5 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -72,7 +72,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -830,9 +830,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -852,13 +852,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb/pf/base/dlb_osdep.h b/drivers/event/dlb/pf/base/dlb_osdep.h
index 0c119b759..14e5f7163 100644
--- a/drivers/event/dlb/pf/base/dlb_osdep.h
+++ b/drivers/event/dlb/pf/base/dlb_osdep.h
@@ -208,7 +208,7 @@ static void *dlb_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb_hw *hw)
 {
 	struct dlb_dev *dlb_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb_dev = container_of(hw, struct dlb_dev, hw);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index c4c34eba5..72f7bffc6 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 3957227bf..20614b570 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -167,7 +167,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -613,7 +613,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -624,7 +624,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -662,7 +662,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -688,7 +688,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -717,9 +717,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -883,9 +883,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index ef650a465..89d6b2bb4 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -618,12 +618,12 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
 		 */
-		if (pthread_create(&thread, NULL, delay_pg_start, ark)) {
+		if (rte_thread_create(&thread, NULL, delay_pg_start, ark)) {
 			ARK_PMD_LOG(ERR, "Could not create pktgen "
 				    "starter thread\n");
 			return -1;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f..96b7da3ac 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f32..93e41aa26 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405..a6f576dab 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b..197c72290 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876..e6f252e09 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729f..cfd436fa6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12..c17f9a8b9 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695a..5f3d9b360 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec19..1e1d6358d 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index b4370e5ac..f48fa9a40 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -523,8 +523,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -677,7 +677,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -731,18 +731,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -928,10 +928,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index b7be3e8e0..0eb02ad37 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -133,7 +133,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -153,7 +153,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 9824cdb6d..fee357a4d 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1043,7 +1043,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1053,20 +1053,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1373,14 +1373,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1459,13 +1459,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1498,14 +1498,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -3839,7 +3839,7 @@ static void bnxt_dev_recover(void *arg)
 	int timeout = bp->fw_reset_max_msecs;
 	int rc = 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	/* Clear Error flag so that device re-init should happen */
 	bp->flags &= ~BNXT_FLAG_FATAL_ERROR;
 
@@ -3876,7 +3876,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -3884,7 +3884,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4035,7 +4035,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4050,7 +4050,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -4832,25 +4832,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5617,14 +5617,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index a29ac2859..8962771f2 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index d94874578..472e6fead 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef9..455d83bef 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061..88d64d703 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd683..26c3e7551 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea..cb6bbcad6 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83..f06bd2b27 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2..1115afa81 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 932600d05..d8305f9ea 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -433,7 +433,7 @@ struct hns3_hw {
 	struct hns3_cmq cmq;
 	struct hns3_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hns3_mbx_arq_ring arq;         /* mailbox async rx queue */
-	pthread_t irq_thread_id;
+	rte_thread_t irq_thread_id;
 	struct hns3_mac mac;
 	unsigned int secondary_cnt; /* Number of secondary processes init'd. */
 	struct hns3_tqp_stats tqp_stats;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index fd20c522d..d78b45866 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1107,7 +1107,7 @@ hns3vf_interrupt_handler(void *param)
 	uint32_t clearval;
 
 	if (hw->irq_thread_id == 0)
-		hw->irq_thread_id = pthread_self();
+		hw->irq_thread_id = rte_thread_self();
 
 	/* Disable interrupt */
 	hns3vf_disable_irq0(hw);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 61d15845e..34d2458b1 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -101,7 +101,7 @@ hns3_get_mbx_resp(struct hns3_hw *hw, uint16_t code0, uint16_t code1,
 		 * Sending mbox in the interrupt thread cannot wait for the
 		 * response, so polling the mbox response on the irq thread.
 		 */
-		if (pthread_equal(hw->irq_thread_id, pthread_self())) {
+		if (rte_thread_equal(hw->irq_thread_id, rte_thread_self())) {
 			in_irq = true;
 			hns3_poll_all_sync_msg();
 		} else {
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 476fd4906..66bc7d683 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -152,7 +152,7 @@ static void
 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 {
 	struct ice_dcf_reset_event_param *param;
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
@@ -165,7 +165,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 	param->vfr = vfr;
 	param->vf_id = vf_id;
 
-	ret = pthread_create(&thread, NULL,
+	ret = rte_thread_create(&thread, NULL,
 			     ice_dcf_vsi_update_service_handler, param);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling");
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 856d21ef9..aa55e6fc0 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 761a0f26b..c76baee58 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4141,7 +4141,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	pthread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca2..272fdcfb8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549..3518b913e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 81eb2e4b0..8ee24fe26 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2335,7 +2335,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index abd7ff70d..57645aed1 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -181,7 +181,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -884,7 +884,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1010,11 +1010,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1046,7 +1046,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1077,7 +1077,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1108,11 +1108,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2234,7 +2234,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index a281fd20e..e767d1f9d 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -632,7 +632,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index 696282ca3..01df52c48 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -902,7 +902,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -918,7 +918,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -945,7 +945,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -953,7 +953,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index 2cc02df32..dce2a6fe6 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_tls_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_tls_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index e37cc65c1..be3500623 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -226,7 +226,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b539928..f0cb71c93 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8..1004ec289 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 1b54d55bd..2052d03a3 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -142,7 +142,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -160,7 +160,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -184,7 +184,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -205,12 +205,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -225,7 +225,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -248,11 +248,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -379,7 +379,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -404,7 +404,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -490,7 +490,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -795,13 +795,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -811,7 +811,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -836,7 +836,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 8a62f7ea7..db393e55b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -56,7 +56,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 05d79bfcc..6f97695e0 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -526,7 +526,7 @@ ifpga_monitor_start_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 0) {
-		ret = pthread_create(&ifpga_monitor_start_thread,
+		ret = rte_thread_create(&ifpga_monitor_start_thread,
 			NULL,
 			ifpga_rawdev_gsd_handle, NULL);
 		if (ret) {
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 6a1b44bc7..1d9fd791e 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -53,7 +53,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -80,7 +80,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -90,7 +90,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -99,7 +99,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -113,7 +113,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -123,7 +123,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -499,7 +499,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, notify_relay,
+	ret = rte_thread_create(&internal->tid, NULL, notify_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create notify relay pthread.");
@@ -511,11 +511,9 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -802,7 +800,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, vring_relay,
+	ret = rte_thread_create(&internal->tid, NULL, vring_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create ring relay pthread.");
@@ -814,11 +812,9 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -1248,9 +1244,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1288,9 +1284,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 4c2d886bd..5065db355 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -763,10 +763,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -797,7 +797,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -806,7 +806,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -815,7 +815,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index 98c71aad4..25c01a74c 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 86adc864f..620268270 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -246,17 +246,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -280,13 +280,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -296,7 +296,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -312,7 +312,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -331,7 +331,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -346,13 +346,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -368,7 +368,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -414,7 +414,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -501,42 +501,33 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
+		rte_thread_attr_init(&attr);
 		CPU_ZERO(&cpuset);
 		if (priv->event_core != -1)
 			CPU_SET(priv->event_core, &cpuset);
 		else
 			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_attr_setaffinity_np(&attr, sizeof(cpuset),
-						  &cpuset);
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
-			return -1;
-		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
@@ -568,7 +559,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -585,8 +575,8 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
 	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
 	priv->timer_tid = 0;
 }
diff --git a/examples/kni/main.c b/examples/kni/main.c
index fe93b8618..e471cc818 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1043,7 +1043,7 @@ main(int argc, char** argv)
 	uint16_t nb_sys_ports, port;
 	unsigned i;
 	void *retval;
-	pthread_t kni_link_tid;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index ca73e7086..29850fc55 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1613,7 +1613,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index 7ea60863d..5572e80f7 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity(thread, sizeof(cpu_set_t), &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring;
 
@@ -672,7 +672,7 @@ new_device(int vid)
 	/* start polling vring */
 	worker_thread_status = WORKER_STATE_START;
 	fprintf(stdout, "New Device %s, Device ID %d\n", path, vid);
-	if (pthread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
+	if (rte_thread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
 		fprintf(stderr, "Worker Thread Started Failed\n");
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 287a89a75..91073dc34 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -1843,7 +1843,7 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	if (rte_thread_get_affinity(rte_thread_self(), sizeof(rte_cpuset_t),
 				&affinity_set))
 		CPU_ZERO(&affinity_set);
 
@@ -1872,7 +1872,7 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	if (rte_thread_get_affinity(rte_thread_self(), sizeof(rte_cpuset_t),
 				&default_set))
 		CPU_ZERO(&default_set);
 
diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
index 6d1af3c0e..6eb2bbb3a 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 5219e783e..387281ad4 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,9 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 int
 rte_thread_self_set_affinity(rte_cpuset_t *cpusetp)
 {
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	if (rte_thread_set_affinity(rte_thread_self(), sizeof(rte_cpuset_t),
 			cpusetp) != 0) {
-		RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n");
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,7 +168,7 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 };
 
 static void *ctrl_thread_init(void *arg)
@@ -184,9 +183,9 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
@@ -194,8 +193,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -211,9 +210,9 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->start_routine = start_routine;
 	params->arg = arg;
 
-	pthread_barrier_init(&params->configured, NULL, 2);
+	rte_thread_barrier_init(&params->configured, 2);
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, (void *)params);
 	if (ret != 0) {
 		free(params);
 		return -ret;
@@ -226,26 +225,26 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity(*thread, sizeof(*cpuset), cpuset);
 	if (ret)
 		goto fail;
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
 	return 0;
 
 fail:
-	if (PTHREAD_BARRIER_SERIAL_THREAD ==
-	    pthread_barrier_wait(&params->configured)) {
-		pthread_barrier_destroy(&params->configured);
+	if (RTE_THREAD_BARRIER_SERIAL_THREAD ==
+	    rte_thread_barrier_wait(&params->configured)) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
-	pthread_cancel(*thread);
-	pthread_join(*thread, NULL);
+	rte_thread_cancel(*thread);
+	rte_thread_join(*thread, NULL);
 	return -ret;
 }
 
@@ -266,7 +265,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+	if (rte_thread_get_affinity(rte_thread_self(), sizeof(cpuset),
 			&cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 24e27387b..6df4a0127 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b8a0d2002..d5a6abe9a 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index c7101b32d..fdc3a2cfe 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 70bd854fe..4cd4e8e70 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
 	'rte_random.c',
 	'rte_reciprocal.c',
 	'rte_service.c',
+	'rte_thread.c',
 	'rte_version.c',
 )
 
diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c
index 62320d610..760c1a858 100644
--- a/lib/librte_eal/freebsd/eal.c
+++ b/lib/librte_eal/freebsd/eal.c
@@ -663,7 +663,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -686,7 +686,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -850,7 +850,13 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(), internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	if (rte_thread_set_affinity(rte_thread_self(), sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,6 +871,20 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr, internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -878,8 +898,9 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr, &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -889,10 +910,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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_alarm.c b/lib/librte_eal/freebsd/eal_alarm.c
index c38b2e04f..e5d7b130b 100644
--- a/lib/librte_eal/freebsd/eal_alarm.c
+++ b/lib/librte_eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/freebsd/eal_interrupts.c b/lib/librte_eal/freebsd/eal_interrupts.c
index 72eeacbc1..de5d2b733 100644
--- a/lib/librte_eal/freebsd/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -725,5 +725,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c
index 1dce9b04f..082a66917 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h
index 0fe0bd839..f895ef8ff 100644
--- a/lib/librte_eal/include/rte_lcore.h
+++ b/lib/librte_eal/include/rte_lcore.h
@@ -370,7 +370,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -387,7 +387,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -436,8 +436,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/librte_eal/include/rte_per_lcore.h b/lib/librte_eal/include/rte_per_lcore.h
index eaedf0cb3..025d97f96 100644
--- a/lib/librte_eal/include/rte_per_lcore.h
+++ b/lib/librte_eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c
index 9ffb4b331..86884e0ea 100644
--- a/lib/librte_eal/linux/eal.c
+++ b/lib/librte_eal/linux/eal.c
@@ -958,7 +958,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -986,7 +986,7 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1214,7 +1214,13 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(), internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	if (rte_thread_set_affinity(rte_thread_self(), sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1228,6 +1234,22 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, (uintptr_t)thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = EINVAL;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr, internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = EINVAL;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1241,8 +1263,9 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr, &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -1255,11 +1278,6 @@ 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_alarm.c b/lib/librte_eal/linux/eal_alarm.c
index 3252c6fa5..f122d2eef 100644
--- a/lib/librte_eal/linux/eal_alarm.c
+++ b/lib/librte_eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,7 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id, rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +228,7 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id, rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/linux/eal_interrupts.c b/lib/librte_eal/linux/eal_interrupts.c
index 1dd994bd1..bc38055b8 100644
--- a/lib/librte_eal/linux/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1558,5 +1558,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c
index 83c2034b9..bd447d6a2 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -164,7 +164,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/lib/librte_eal/linux/eal_timer.c b/lib/librte_eal/linux/eal_timer.c
index 7cf15caba..b4099a0aa 100644
--- a/lib/librte_eal/linux/eal_timer.c
+++ b/lib/librte_eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index 474cf123f..ff544fa99 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -329,6 +329,25 @@ EXPORTS
 	rte_thread_tls_key_delete
 	rte_thread_tls_value_get
 	rte_thread_tls_value_set
+	rte_thread_mutex_lock
+	rte_thread_mutex_unlock
+	rte_thread_mutex_init
+	rte_thread_mutex_destroy
+	rte_thread_create
+	rte_thread_set_affinity
+	rte_thread_get_affinity
+	rte_thread_set_priority
+	rte_thread_attr_init
+	rte_thread_attr_set_affinity
+	rte_thread_attr_get_affinity
+	rte_thread_attr_set_priority
+	rte_thread_join
+	rte_thread_self
+	rte_thread_equal
+	rte_thread_barrier_init
+	rte_thread_barrier_wait
+	rte_thread_barrier_destroy
+	rte_thread_cancel
 
 	rte_mem_lock
 	rte_mem_map
diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build
index 71221b84a..d3af6b6fe 100644
--- a/lib/librte_eal/unix/meson.build
+++ b/lib/librte_eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
 	'eal_file.c',
 	'eal_unix_memory.c',
 	'eal_unix_timer.c',
-	'rte_thread.c',
 )
diff --git a/lib/librte_eal/unix/rte_thread.c b/lib/librte_eal/unix/rte_thread.c
deleted file mode 100644
index 86ffeebc9..000000000
--- a/lib/librte_eal/unix/rte_thread.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_tls_key_delete(rte_tls_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_tls_value_set(rte_tls_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_tls_value_get(rte_tls_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index 756c60ed1..f1daa5b9a 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -419,6 +419,27 @@ EXPERIMENTAL {
 	rte_thread_tls_key_delete;
 	rte_thread_tls_value_get;
 	rte_thread_tls_value_set;
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity;
+	rte_thread_get_affinity;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 2fc3d6141..906a4b20a 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -368,6 +368,26 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	ret = rte_thread_set_priority(rte_thread_self(), internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr, internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -384,7 +404,9 @@ rte_eal_init(int argc, char **argv)
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
+					eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
index 3b8266d38..9839a1fed 100644
--- a/lib/librte_eal/windows/eal_interrupts.c
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -7,7 +7,7 @@
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +76,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -94,7 +94,7 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 
 	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread(%lu)", intr_thread);
 		return -ENOENT;
 	}
 
diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c
index 9c3f6d69f..5ed495562 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -60,11 +60,11 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index dc5dc8240..4b92b198c 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/librte_eal/windows/include/meson.build b/lib/librte_eal/windows/include/meson.build
index b3534b025..7d9b3393e 100644
--- a/lib/librte_eal/windows/include/meson.build
+++ b/lib/librte_eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
deleted file mode 100644
index 9aeab1fa7..000000000
--- a/lib/librte_eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/librte_eal/windows/include/sched.h b/lib/librte_eal/windows/include/sched.h
index fbe07f742..ac2c3d8fc 100644
--- a/lib/librte_eal/windows/include/sched.h
+++ b/lib/librte_eal/windows/include/sched.h
@@ -43,7 +43,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 42ff5c2d5..ffcddcd0c 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
 	'eal_timer.c',
 	'fnmatch.c',
 	'getopt.c',
-	'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'librte_eal/common/rte_thread.c'
+else
+	sources += 'librte_eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 6f514c388..3ae7687f8 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,7 +506,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -580,7 +580,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 918a34ed1..580108b95 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -5,7 +5,6 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
 #include <sys/types.h>
 
 /**
@@ -183,7 +182,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 241af6c4c..d096c3d57 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -223,14 +223,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index d8c635e99..33d8c7b54 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -121,7 +121,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1302,12 +1302,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 55d4856f9..b97774ccd 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index 3ab5cfdd6..ba58d849e 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 0169d3648..5f41d40ba 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,11 +1122,11 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 52ab93d1e..54db845da 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -646,7 +646,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -655,7 +655,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -663,12 +663,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 3b8c5d316..29f8df218 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -32,5 +32,7 @@ option('enable_trace_fp', type: 'boolean', value: false,
 	description: 'enable fast path trace points.')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false,
 	description: 'use HPET timer in EAL')
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH 1/3] Add EAL threads API
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
@ 2021-03-18 14:48   ` Tal Shnaiderman
  2021-03-18 19:42     ` Narcisa Ana Maria Vasile
  2021-03-18 20:04     ` Tyler Retzlaff
  2021-03-18 15:48   ` David Marchand
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2 siblings, 2 replies; 290+ messages in thread
From: Tal Shnaiderman @ 2021-03-18 14:48 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile, dev, NBU-Contact-Thomas Monjalon,
	dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

> Subject: [dpdk-dev] [PATCH 1/3] Add EAL threads API
> 
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> EAL must hide the environment specifics from apps and libraries.
> Add an EAL API for managing threads.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
> ---

Hi Naty, Dmitry, 

Thank you for adding those functions to the thread API.
This is a huge commit, I'd split it to separate patches, something like:

1) Move existing code to rte_thread.
2) Add empty stubs for new functions.
3) Implement OS functions for thread creation/join.
4) Implement OS functions for thread affinity.
5) Implement OS functions for thread priority.

>  lib/librte_eal/common/eal_common_thread.c     |   6 +-
>  lib/librte_eal/common/rte_thread.c            | 346 ++++++++++++
>  lib/librte_eal/include/rte_thread.h           | 323 ++++++++++-
>  lib/librte_eal/include/rte_thread_types.h     |  20 +
>  lib/librte_eal/windows/eal_lcore.c            | 167 ++++--
>  lib/librte_eal/windows/eal_windows.h          |  10 +
>  .../include/rte_windows_thread_types.h        |  19 +
>  lib/librte_eal/windows/rte_thread.c           | 507 +++++++++++++++++-
>  8 files changed, 1338 insertions(+), 60 deletions(-)  create mode 100644

<snip>

> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -1,16 +1,503 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
>   * Copyright 2021 Mellanox Technologies, Ltd
> + * Copyright(c) 2021 Microsoft Corporation
>   */
> 
>  #include <rte_common.h>
> -#include <rte_errno.h>
>  #include <rte_thread.h>
> -#include <rte_windows.h>
> +
> +#include "eal_windows.h"
> 
>  struct eal_tls_key {
>  	DWORD thread_index;
>  };
> 

I don't know if this table is needed, the approach should be to have the return value/rte_errno identical between the OSs.
And having the specific OS errno printed.

e.g. pthread_setschedparam On UNIX returns ESRCH when no thread id is found, the table below doesn't translate to it so Windows
will never return such error code, maybe use only the errnos below for all OSs? what do you think?

> +/* Translates the most common error codes related to threads */ static
> +int rte_thread_translate_win32_error(DWORD error) {
> +	switch (error) {
> +	case ERROR_SUCCESS:
> +		return 0;
> +
> +	case ERROR_INVALID_PARAMETER:
> +		return -EINVAL;
> +
> +	case ERROR_INVALID_HANDLE:
> +		return -EFAULT;
> +
> +	case ERROR_NOT_ENOUGH_MEMORY:
> +	/* FALLTHROUGH */
> +	case ERROR_NO_SYSTEM_RESOURCES:
> +		return -ENOMEM;
> +
> +	case ERROR_PRIVILEGE_NOT_HELD:
> +	/* FALLTHROUGH */
> +	case ERROR_ACCESS_DENIED:
> +		return -EACCES;
> +
> +	case ERROR_ALREADY_EXISTS:
> +		return -EEXIST;
> +
> +	case ERROR_POSSIBLE_DEADLOCK:
> +		return -EDEADLK;
> +
> +	case ERROR_INVALID_FUNCTION:
> +	/* FALLTHROUGH */
> +	case ERROR_CALL_NOT_IMPLEMENTED:
> +		return -ENOSYS;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return -EINVAL;
> +}
</snip>

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH 1/3] Add EAL threads API
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
  2021-03-18 14:48   ` Tal Shnaiderman
@ 2021-03-18 15:48   ` David Marchand
  2021-03-18 19:40     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2 siblings, 1 reply; 290+ messages in thread
From: David Marchand @ 2021-03-18 15:48 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, Thomas Monjalon, Dmitry Kozlyuk, Khoa To, navasile,
	Dmitry Malloy (MESHCHANINOV),
	roretzla, Omar Cardona, Bruce Richardson, Pallavi Kadam

On Thu, Mar 18, 2021 at 2:01 AM Narcisa Ana Maria Vasile
<navasile@linux.microsoft.com> wrote:
> diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
> index 73a055902..5219e783e 100644
> --- a/lib/librte_eal/common/eal_common_thread.c
> +++ b/lib/librte_eal/common/eal_common_thread.c
> @@ -84,7 +84,7 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
>  }
>
>  int
> -rte_thread_set_affinity(rte_cpuset_t *cpusetp)
> +rte_thread_self_set_affinity(rte_cpuset_t *cpusetp)
>  {
>         if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
>                         cpusetp) != 0) {

[snip]

> diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
> index e640ea185..66b112bc4 100644
> --- a/lib/librte_eal/include/rte_thread.h
> +++ b/lib/librte_eal/include/rte_thread.h

[snip]

> +/**
> + * Set the affinity of thread 'thread_id' to the cpu set
> + * specified by 'cpuset'.
> + *
> + * @param thread_id
> + *    Id of the thread for which to set the affinity.
> + *
> + * @param cpuset_size
> + *
> + * @param cpuset
> + *   Pointer to CPU affinity to set.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return nonzero.
> + */
> +__rte_experimental
> +int rte_thread_set_affinity(rte_thread_t thread_id, size_t cpuset_size,
> +                           const rte_cpuset_t *cpuset);
> +

[snip]

> @@ -34,7 +353,7 @@ typedef struct eal_tls_key *rte_tls_key;
>   * @return
>   *   On success, return 0; otherwise return -1;
>   */
> -int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
> +int rte_thread_self_set_affinity(rte_cpuset_t *cpusetp);
>
>  /**
>   * Get core affinity of the current thread.

rte_thread_*et_affinity() are stable.
This breaks the ABI (which is bad) and this API change was not
announced previously.

The ABI check will catch it for you if you stop at this patch (the
patch 3 actually makes the check go silent because of a wrong
version.map update with duplicate symbols).

$ DPDK_ABI_REF_VERSION=v21.02 ./devtools/test-meson-builds.sh
...
[2502/2502] Linking target drivers/librte_event_octeontx2.so.21.2
Error: ABI issue reported for 'abidiff --suppr
/home/dmarchan/dpdk/devtools/../devtools/libabigail.abignore
--no-added-syms --headers-dir1
/home/dmarchan/abi/v21.02/build-gcc-shared/usr/local/include
--headers-dir2 /home/dmarchan/builds/build-gcc-shared/install/usr/local/include
/home/dmarchan/abi/v21.02/build-gcc-shared/dump/librte_eal.dump
/home/dmarchan/builds/build-gcc-shared/install/dump/librte_eal.dump'
ABIDIFF_ABI_CHANGE, this change requires a review (abidiff flagged
this as a potential issue).
ABIDIFF_ABI_INCOMPATIBLE_CHANGE, this change breaks the ABI.

$ abidiff --suppr
/home/dmarchan/dpdk/devtools/../devtools/libabigail.abignore
--no-added-syms --headers-dir1
/home/dmarchan/abi/v21.02/build-gcc-shared/usr/local/include
--headers-dir2 /home/dmarchan/builds/build-gcc-shared/install/usr/local/include
/home/dmarchan/abi/v21.02/build-gcc-shared/dump/librte_eal.dump
/home/dmarchan/builds/build-gcc-shared/install/dump/librte_eal.dump
Functions changes summary: 2 Removed, 0 Changed, 0 Added (6 filtered
out) functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Variable symbols changes summary: 0 Removed, 0 Added variable symbol
not referenced by debug info

2 Removed functions:

  [D] 'function void rte_thread_get_affinity(rte_cpuset_t*)'
{rte_thread_get_affinity@@DPDK_21}
  [D] 'function int rte_thread_set_affinity(rte_cpuset_t*)'
{rte_thread_set_affinity@@DPDK_21}


-- 
David Marchand


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH 1/3] Add EAL threads API
  2021-03-18 15:48   ` David Marchand
@ 2021-03-18 19:40     ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-18 19:40 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, Thomas Monjalon, Dmitry Kozlyuk, Khoa To, navasile,
	Dmitry Malloy (MESHCHANINOV),
	roretzla, Omar Cardona, Bruce Richardson, Pallavi Kadam

On Thu, Mar 18, 2021 at 04:48:49PM +0100, David Marchand wrote:
> On Thu, Mar 18, 2021 at 2:01 AM Narcisa Ana Maria Vasile
> <navasile@linux.microsoft.com> wrote:
> > diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
> > index 73a055902..5219e783e 100644
> > --- a/lib/librte_eal/common/eal_common_thread.c
> 
> rte_thread_*et_affinity() are stable.
> This breaks the ABI (which is bad) and this API change was not
> announced previously.
> 
  Thank you David, I will revert the renaming of the stable
  functions to fix the ABI break.

  Given that the original functions only operate on the current thread
  (using the _thread_self()), changing their names to 
  rte_thread_self_*et_affinity() brings more clarity to the purpose of
  the functions. We will propose an ABI change to rename
  them in the next release (following the proper ABI changes procedures).

> -- 
> David Marchand

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH 1/3] Add EAL threads API
  2021-03-18 14:48   ` Tal Shnaiderman
@ 2021-03-18 19:42     ` Narcisa Ana Maria Vasile
  2021-03-18 20:04     ` Tyler Retzlaff
  1 sibling, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-18 19:42 UTC (permalink / raw)
  To: Tal Shnaiderman
  Cc: dev, NBU-Contact-Thomas Monjalon, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Thu, Mar 18, 2021 at 02:48:01PM +0000, Tal Shnaiderman wrote:
> > Subject: [dpdk-dev] [PATCH 1/3] Add EAL threads API
> > 
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > EAL must hide the environment specifics from apps and libraries.
> > Add an EAL API for managing threads.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
> > ---
> 
> Hi Naty, Dmitry, 
> 
> Thank you for adding those functions to the thread API.
> This is a huge commit, I'd split it to separate patches, something like:
> 
  Thank you Tal, I will split this patch into smaller ones.
   

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH 1/3] Add EAL threads API
  2021-03-18 14:48   ` Tal Shnaiderman
  2021-03-18 19:42     ` Narcisa Ana Maria Vasile
@ 2021-03-18 20:04     ` Tyler Retzlaff
  1 sibling, 0 replies; 290+ messages in thread
From: Tyler Retzlaff @ 2021-03-18 20:04 UTC (permalink / raw)
  To: Tal Shnaiderman
  Cc: Narcisa Ana Maria Vasile, dev, NBU-Contact-Thomas Monjalon,
	dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Thu, Mar 18, 2021 at 02:48:01PM +0000, Tal Shnaiderman wrote:
> 
> I don't know if this table is needed, the approach should be to have the return value/rte_errno identical between the OSs.
> And having the specific OS errno printed.

the underlying problem here is that dpdk is adopting linux errno spaces
as the de-facto standard.  even between bsd and linux some apis will
return different errno for the same input parameters.

between linux/bsd/unix this ends up being more subtle since usually the
alternate errno returned is still handled by the consumer of the api
in a similar manner but arguably could result in different behavior on
different platforms for the same application i.e. compatibility delta.

with windows the problem is more pronounced. calls to the underlying
native apis may fail with errors that semantically can't be represented
by the linux errno space or may not return an error at all. in such
circumstances a more generic errno is returned or the call succeeds
where it may have failed on another platform.  i.e. compatibility delta.

the patch as presented aims to be as semantically compatible as possible
with the current adopted linux errno space. we try to remap the underlying
platform error to something that makes sense within the set of linux errno
that we are allowed to return and when we can't map it we return a more
generic errno. if we've made mistakes here, please let us know.

i think there is probably a more general discussion to be had that is
off-topic for this patch about how to report errors portably in dpdk and
at the same time preserve and provide access to the underlying platform
details of the errors when needed.

> e.g. pthread_setschedparam On UNIX returns ESRCH when no thread id is found, the table below doesn't translate to it so Windows
> will never return such error code, maybe use only the errnos below for all OSs? what do you think?
> 
> > +/* Translates the most common error codes related to threads */ static
> > +int rte_thread_translate_win32_error(DWORD error) {
> > +	switch (error) {
> > +	case ERROR_SUCCESS:
> > +		return 0;
> > +
> > +	case ERROR_INVALID_PARAMETER:
> > +		return -EINVAL;
> > +
> > +	case ERROR_INVALID_HANDLE:
> > +		return -EFAULT;
> > +
> > +	case ERROR_NOT_ENOUGH_MEMORY:
> > +	/* FALLTHROUGH */
> > +	case ERROR_NO_SYSTEM_RESOURCES:
> > +		return -ENOMEM;
> > +
> > +	case ERROR_PRIVILEGE_NOT_HELD:
> > +	/* FALLTHROUGH */
> > +	case ERROR_ACCESS_DENIED:
> > +		return -EACCES;
> > +
> > +	case ERROR_ALREADY_EXISTS:
> > +		return -EEXIST;
> > +
> > +	case ERROR_POSSIBLE_DEADLOCK:
> > +		return -EDEADLK;
> > +
> > +	case ERROR_INVALID_FUNCTION:
> > +	/* FALLTHROUGH */
> > +	case ERROR_CALL_NOT_IMPLEMENTED:
> > +		return -ENOSYS;
> > +
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> </snip>

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading
  2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
  2021-03-18 14:48   ` Tal Shnaiderman
  2021-03-18 15:48   ` David Marchand
@ 2021-03-23  0:20   ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                       ` (10 more replies)
  2 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application. The two options above are available:

 --thread-prio normal
 --thread-prio realtime
 
Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  windows/eal: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  54 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  55 +-
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |  36 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 +-
 lib/librte_eal/common/eal_common_thread.c     |  43 +-
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_internal_cfg.h      |   2 +
 lib/librte_eal/common/eal_options.h           |   2 +
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +-
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/common/rte_thread.c            | 342 ++++++++++++
 lib/librte_eal/freebsd/eal.c                  |  37 +-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/include/rte_thread.h           | 333 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/linux/eal.c                    |  42 +-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  19 +
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  86 ---
 lib/librte_eal/version.map                    |  21 +
 lib/librte_eal/windows/eal.c                  |  26 +-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_lcore.c            | 170 ++++--
 lib/librte_eal/windows/eal_thread.c           |  24 +-
 lib/librte_eal/windows/eal_windows.h          |  20 +-
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 -------
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_eal/windows/rte_thread.c           | 516 +++++++++++++++++-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 +-
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++---
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2034 insertions(+), 906 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  2:54       ` Stephen Hemminger
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                       ` (9 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add the thread identifier type.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 101 ++++++++++++++++++
 lib/librte_eal/include/rte_thread.h           |  39 ++++++-
 lib/librte_eal/include/rte_thread_types.h     |  12 +++
 .../include/rte_windows_thread_types.h        |  12 +++
 lib/librte_eal/windows/rte_thread.c           |  13 +++
 5 files changed, 174 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
new file mode 100644
index 000000000..9b5cee890
--- /dev/null
+++ b/lib/librte_eal/common/rte_thread.c
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return pthread_self();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1, t2);
+}
+
+int
+rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_tls_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_tls_key_delete(rte_tls_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_tls_value_set(rte_tls_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_tls_value_get(rte_tls_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index e640ea185..566c4c09f 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_os.h>
@@ -20,11 +21,43 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_tls_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
@@ -59,7 +92,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -73,7 +106,7 @@ int rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *));
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_tls_key_delete(rte_tls_key key);
@@ -88,7 +121,7 @@ int rte_thread_tls_key_delete(rte_tls_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_tls_value_set(rte_tls_key key, const void *value);
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
new file mode 100644
index 000000000..19fb85e38
--- /dev/null
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+typedef pthread_t                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 000000000..ebd3d9e8f
--- /dev/null
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+typedef DWORD                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 2e2ab2917..43c09b2f3 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,18 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1 == t2 ? 1 : 0;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 02/10] eal: add thread attributes
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority

Implement functions for managing thread attributes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 53 ++++++++++++
 lib/librte_eal/include/rte_thread.h           | 82 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/librte_eal/windows/rte_thread.c           | 56 +++++++++++++
 5 files changed, 197 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 9b5cee890..b21eac0e2 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,59 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 566c4c09f..1701a05cd 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -28,6 +28,19 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,
+	/*
+	 * This enum can be extended to allow more priority levels.
+	 */
+};
+
+typedef struct {
+	enum rte_thread_priority priority;
+	rte_cpuset_t cpuset;
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -58,6 +71,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr;
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+				 enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 19fb85e38..a884daf17 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 typedef pthread_t                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index ebd3d9e8f..8cb4b3856 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 typedef DWORD                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 43c09b2f3..d0294d179 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -24,6 +24,62 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to init thread attributes, invalid parameter\n");
+		return EINVAL;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/windows/rte_thread.c | 59 ++++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 9 deletions(-)

diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index d0294d179..c948b2c5e 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -12,6 +12,47 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int rte_thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+
+	default:
+		return EINVAL;
+	}
+
+	return EINVAL;
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -87,13 +128,13 @@ rte_thread_tls_key_create(rte_tls_key *key,
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
 		RTE_LOG_WIN32_ERR("TlsAlloc()");
 		free(*key);
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -101,14 +142,14 @@ rte_thread_tls_key_create(rte_tls_key *key,
 int
 rte_thread_tls_key_delete(rte_tls_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
 		RTE_LOG_WIN32_ERR("TlsFree()");
 		free(key);
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	free(key);
 	return 0;
@@ -119,15 +160,15 @@ rte_thread_tls_value_set(rte_tls_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
 		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -137,7 +178,7 @@ rte_thread_tls_value_get(rte_tls_key key)
 {
 	void *output;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 04/10] eal: implement functions for thread affinity management
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (2 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c   |  13 ++
 lib/librte_eal/include/rte_thread.h  |  41 +++++++
 lib/librte_eal/windows/eal_lcore.c   | 170 +++++++++++++++++++--------
 lib/librte_eal/windows/eal_windows.h |  10 ++
 lib/librte_eal/windows/rte_thread.c  | 132 ++++++++++++++++++++-
 5 files changed, 318 insertions(+), 48 deletions(-)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index b21eac0e2..9df98263e 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,19 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id, cpuset_size, cpuset);
+}
+
+int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 1701a05cd..05fb2cb0f 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -71,6 +71,47 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset_size
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset_size
+ *    Size of the cpu set.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
index a85149be9..023c5c895 100644
--- a/lib/librte_eal/windows/eal_lcore.c
+++ b/lib/librte_eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -28,13 +27,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -48,13 +49,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -79,57 +178,27 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
-		}
+		if (eal_check_for_duplicate_numa(info))
+			break;
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -139,7 +208,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -165,3 +234,12 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	if (cpu_index < CPU_SETSIZE)
+		return &cpu_map.cpus[cpu_index];
+
+	return NULL;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index 478accc1b..dc5dc8240 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index c948b2c5e..865b1b781 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -4,9 +4,9 @@
  */
 
 #include <rte_common.h>
-#include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -65,6 +65,134 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+			    size_t cpuset_size,
+			    const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 05/10] eal: implement thread priority management functions
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (3 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                       ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 25 ++++++++++
 lib/librte_eal/include/rte_thread.h | 17 +++++++
 lib/librte_eal/windows/rte_thread.c | 76 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 9df98263e..9e0d710dd 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -42,6 +42,31 @@ int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
 	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
 }
 
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int policy;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+
+
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+		policy = SCHED_RR;
+		param.sched_priority = priority;
+	} else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+		policy = SCHED_OTHER;
+		param.sched_priority = priority;
+	} else {
+		RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+				    "Defaulting to priority 'normal'.\n");
+		policy = SCHED_OTHER;
+	}
+
+	return pthread_setschedparam(thread_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 05fb2cb0f..ac4011565 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -112,6 +112,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 				  rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 865b1b781..3fb283ecb 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -193,6 +193,82 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	DWORD priority_class = NORMAL_PRIORITY_CLASS;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	switch (priority) {
+
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		priority_class = REALTIME_PRIORITY_CLASS;
+		break;
+
+	case RTE_THREAD_PRIORITY_NORMAL:
+	/* FALLTHROUGH */
+	default:
+		priority_class = NORMAL_PRIORITY_CLASS;
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+		break;
+	}
+
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, priority)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 06/10] eal: add thread lifetime management
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (4 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                       ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 110 ++++++++++++++++++++++++
 lib/librte_eal/include/rte_thread.h |  53 ++++++++++++
 lib/librte_eal/windows/rte_thread.c | 125 ++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 9e0d710dd..7feaf55ee 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -120,6 +120,116 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(thread_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id);
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index ac4011565..806dd8780 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -198,6 +198,59 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 				 enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 3fb283ecb..c42f0ea93 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -325,6 +325,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+
+	thread_handle = CreateThread(NULL, 0,
+				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,
+				args, 0, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("CreateThread()");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = rte_thread_translate_win32_error(GetLastError());
+				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = rte_thread_translate_win32_error(GetLastError());
+			RTE_LOG_WIN32_ERR("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 07/10] eal: implement functions for mutex management
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (5 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 24 ++++++++
 lib/librte_eal/include/rte_thread.h           | 55 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  1 +
 lib/librte_eal/windows/rte_thread.c           | 28 ++++++++++
 5 files changed, 111 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 7feaf55ee..6e0f970af 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -220,6 +220,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 806dd8780..b72f4818e 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -238,6 +238,61 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @param attr
+ *    Attributes for initialization of the mutex.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index a884daf17..37bc7af2b 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,9 +7,12 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
 #define EAL_THREAD_PRIORITY_NORMAL               0
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
 
 typedef pthread_t                       rte_thread_t;
+typedef pthread_mutex_t                 rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 8cb4b3856..47c6b2664 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -11,5 +11,6 @@
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
+typedef CRITICAL_SECTION            rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index c42f0ea93..8a2c7691a 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -417,6 +417,34 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 08/10] eal: implement functions for thread barrier management
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (6 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                       ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 16 +++++++
 lib/librte_eal/include/rte_thread.h           | 46 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  2 +
 .../include/rte_windows_thread_types.h        |  3 ++
 lib/librte_eal/windows/rte_thread.c           | 27 +++++++++++
 5 files changed, 94 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 6e0f970af..0295bf874 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -244,6 +244,22 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	return pthread_barrier_init(barrier, NULL, count);
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_wait(barrier);
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_destroy(barrier);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index b72f4818e..7ad622752 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -293,6 +293,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 37bc7af2b..b055bbf67 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
 #define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
 
 #define EAL_THREAD_PRIORITY_NORMAL               0
@@ -14,5 +15,6 @@
 
 typedef pthread_t                       rte_thread_t;
 typedef pthread_mutex_t                 rte_thread_mutex_t;
+typedef pthread_barrier_t               rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 47c6b2664..b6209e6eb 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,10 +7,13 @@
 
 #include <rte_windows.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
+
 #define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
 typedef CRITICAL_SECTION            rte_thread_mutex_t;
+typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 8a2c7691a..0d7cae254 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -445,6 +445,33 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+
+	if (!InitializeSynchronizationBarrier(barrier, count, -1)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("InitializeSynchronizationBarrier()");
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return EnterSynchronizationBarrier(barrier,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	DeleteSynchronizationBarrier(barrier);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 09/10] eal: add EAL argument for setting thread priority
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (7 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can select the thread priority to be either 'normal'
or 'critical':
--thread-prio normal
--thread-prio realtime

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/eal_common_options.c | 28 +++++++++++++++++++++-
 lib/librte_eal/common/eal_internal_cfg.h   |  2 ++
 lib/librte_eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 622c7bc42..287a89a75 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -106,6 +106,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1383,6 +1384,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1796,7 +1815,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2059,6 +2084,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 51dbe86e2..7ab1d0008 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -93,6 +93,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 7b348e707..9f5b209f6 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v2 10/10] Enable the new EAL thread API
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (8 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-23  0:20     ` Narcisa Ana Maria Vasile
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-23  0:20 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +--
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  54 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 ++--
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  55 +++---
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |   8 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 ++---
 lib/librte_eal/common/eal_common_thread.c     |  43 ++--
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +--
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/freebsd/eal.c                  |  37 +++-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/linux/eal.c                    |  42 +++-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  19 ++
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  86 --------
 lib/librte_eal/version.map                    |  21 ++
 lib/librte_eal/windows/eal.c                  |  26 ++-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_thread.c           |  24 +--
 lib/librte_eal/windows/eal_windows.h          |  10 -
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------------------
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 ++--
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++++++------
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 653 insertions(+), 845 deletions(-)
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index 27f1b1c0e..ff284335a 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 #endif
 #endif
 
@@ -127,7 +127,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
-		pthread_create(&thread, NULL, &send_pkts, NULL);
+		rte_thread_create(&thread, NULL, &send_pkts, NULL);
 #endif
 #endif
 
@@ -137,7 +137,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fc..c507e423e 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a..3d9663f5e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d06..ce79d9c17 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 3cf560b8a..990fe6681 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -255,6 +255,10 @@ else # for 32-bit we need smaller reserved memory areas
 	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index 750b756b9..3621a7190 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -37,10 +37,10 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
-		error(0, ret, "pthread_getaffinity_np()");
+		error(0, ret, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a..dc5f02bec 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681c..6d2d10cdf 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1..c826ad0c1 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -92,10 +92,10 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index 46255ab5e..43af76ec5 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -72,7 +72,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -830,9 +830,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -852,13 +852,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb/pf/base/dlb_osdep.h b/drivers/event/dlb/pf/base/dlb_osdep.h
index 0c119b759..14e5f7163 100644
--- a/drivers/event/dlb/pf/base/dlb_osdep.h
+++ b/drivers/event/dlb/pf/base/dlb_osdep.h
@@ -208,7 +208,7 @@ static void *dlb_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb_hw *hw)
 {
 	struct dlb_dev *dlb_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb_dev = container_of(hw, struct dlb_dev, hw);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index c4c34eba5..72f7bffc6 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 3957227bf..20614b570 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -167,7 +167,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -613,7 +613,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -624,7 +624,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -662,7 +662,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -688,7 +688,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -717,9 +717,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -883,9 +883,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index ef650a465..89d6b2bb4 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -618,12 +618,12 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
 		 */
-		if (pthread_create(&thread, NULL, delay_pg_start, ark)) {
+		if (rte_thread_create(&thread, NULL, delay_pg_start, ark)) {
 			ARK_PMD_LOG(ERR, "Could not create pktgen "
 				    "starter thread\n");
 			return -1;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f..96b7da3ac 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f32..93e41aa26 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405..a6f576dab 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b..197c72290 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876..e6f252e09 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729f..cfd436fa6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12..c17f9a8b9 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695a..5f3d9b360 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec19..1e1d6358d 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index b4370e5ac..f48fa9a40 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -523,8 +523,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -677,7 +677,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -731,18 +731,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -928,10 +928,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index b7be3e8e0..0eb02ad37 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -133,7 +133,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -153,7 +153,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 9824cdb6d..fee357a4d 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1043,7 +1043,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1053,20 +1053,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1373,14 +1373,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1459,13 +1459,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1498,14 +1498,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -3839,7 +3839,7 @@ static void bnxt_dev_recover(void *arg)
 	int timeout = bp->fw_reset_max_msecs;
 	int rc = 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	/* Clear Error flag so that device re-init should happen */
 	bp->flags &= ~BNXT_FLAG_FATAL_ERROR;
 
@@ -3876,7 +3876,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -3884,7 +3884,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4035,7 +4035,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4050,7 +4050,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -4832,25 +4832,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5617,14 +5617,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index a29ac2859..8962771f2 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index d94874578..472e6fead 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef9..455d83bef 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061..88d64d703 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd683..26c3e7551 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea..cb6bbcad6 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83..f06bd2b27 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2..1115afa81 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 932600d05..d8305f9ea 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -433,7 +433,7 @@ struct hns3_hw {
 	struct hns3_cmq cmq;
 	struct hns3_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hns3_mbx_arq_ring arq;         /* mailbox async rx queue */
-	pthread_t irq_thread_id;
+	rte_thread_t irq_thread_id;
 	struct hns3_mac mac;
 	unsigned int secondary_cnt; /* Number of secondary processes init'd. */
 	struct hns3_tqp_stats tqp_stats;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index fd20c522d..d78b45866 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1107,7 +1107,7 @@ hns3vf_interrupt_handler(void *param)
 	uint32_t clearval;
 
 	if (hw->irq_thread_id == 0)
-		hw->irq_thread_id = pthread_self();
+		hw->irq_thread_id = rte_thread_self();
 
 	/* Disable interrupt */
 	hns3vf_disable_irq0(hw);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 61d15845e..34d2458b1 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -101,7 +101,7 @@ hns3_get_mbx_resp(struct hns3_hw *hw, uint16_t code0, uint16_t code1,
 		 * Sending mbox in the interrupt thread cannot wait for the
 		 * response, so polling the mbox response on the irq thread.
 		 */
-		if (pthread_equal(hw->irq_thread_id, pthread_self())) {
+		if (rte_thread_equal(hw->irq_thread_id, rte_thread_self())) {
 			in_irq = true;
 			hns3_poll_all_sync_msg();
 		} else {
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 476fd4906..66bc7d683 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -152,7 +152,7 @@ static void
 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 {
 	struct ice_dcf_reset_event_param *param;
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
@@ -165,7 +165,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 	param->vfr = vfr;
 	param->vf_id = vf_id;
 
-	ret = pthread_create(&thread, NULL,
+	ret = rte_thread_create(&thread, NULL,
 			     ice_dcf_vsi_update_service_handler, param);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling");
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 856d21ef9..aa55e6fc0 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 761a0f26b..c76baee58 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4141,7 +4141,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	pthread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca2..272fdcfb8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549..3518b913e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 81eb2e4b0..8ee24fe26 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2335,7 +2335,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index abd7ff70d..57645aed1 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -181,7 +181,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -884,7 +884,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1010,11 +1010,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1046,7 +1046,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1077,7 +1077,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1108,11 +1108,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2234,7 +2234,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index a281fd20e..e767d1f9d 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -632,7 +632,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index 696282ca3..01df52c48 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -902,7 +902,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -918,7 +918,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -945,7 +945,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -953,7 +953,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index 2cc02df32..dce2a6fe6 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_tls_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_tls_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index e37cc65c1..be3500623 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -226,7 +226,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b539928..f0cb71c93 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8..1004ec289 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 1b54d55bd..2052d03a3 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -142,7 +142,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -160,7 +160,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -184,7 +184,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -205,12 +205,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -225,7 +225,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -248,11 +248,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -379,7 +379,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -404,7 +404,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -490,7 +490,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -795,13 +795,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -811,7 +811,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -836,7 +836,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 8a62f7ea7..db393e55b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -56,7 +56,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 05d79bfcc..6f97695e0 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -526,7 +526,7 @@ ifpga_monitor_start_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 0) {
-		ret = pthread_create(&ifpga_monitor_start_thread,
+		ret = rte_thread_create(&ifpga_monitor_start_thread,
 			NULL,
 			ifpga_rawdev_gsd_handle, NULL);
 		if (ret) {
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 6a1b44bc7..1d9fd791e 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -53,7 +53,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -80,7 +80,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -90,7 +90,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -99,7 +99,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -113,7 +113,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -123,7 +123,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -499,7 +499,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, notify_relay,
+	ret = rte_thread_create(&internal->tid, NULL, notify_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create notify relay pthread.");
@@ -511,11 +511,9 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -802,7 +800,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, vring_relay,
+	ret = rte_thread_create(&internal->tid, NULL, vring_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create ring relay pthread.");
@@ -814,11 +812,9 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -1248,9 +1244,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1288,9 +1284,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 4c2d886bd..5065db355 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -763,10 +763,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -797,7 +797,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -806,7 +806,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -815,7 +815,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index 98c71aad4..25c01a74c 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 86adc864f..55b184e56 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -246,17 +246,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -280,13 +280,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -296,7 +296,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -312,7 +312,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -331,7 +331,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -346,13 +346,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -368,7 +368,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -414,7 +414,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -501,42 +501,34 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
+		rte_thread_attr_init(&attr);
 		CPU_ZERO(&cpuset);
 		if (priv->event_core != -1)
 			CPU_SET(priv->event_core, &cpuset);
 		else
 			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_attr_setaffinity_np(&attr, sizeof(cpuset),
-						  &cpuset);
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
-			return -1;
-		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr,
+					RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
@@ -568,7 +560,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -585,8 +576,8 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
 	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
 	priv->timer_tid = 0;
 }
diff --git a/examples/kni/main.c b/examples/kni/main.c
index fe93b8618..d29cbf7ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index ca73e7086..29850fc55 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1613,7 +1613,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index 7ea60863d..5ea1b45ac 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, sizeof(cpu_set_t), &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring;
 
@@ -672,7 +672,7 @@ new_device(int vid)
 	/* start polling vring */
 	worker_thread_status = WORKER_STATE_START;
 	fprintf(stdout, "New Device %s, Device ID %d\n", path, vid);
-	if (pthread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
+	if (rte_thread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
 		fprintf(stderr, "Worker Thread Started Failed\n");
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 287a89a75..839d837f2 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -1843,8 +1843,8 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t),  &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1872,8 +1872,8 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					  sizeof(rte_cpuset_t), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
index 6d1af3c0e..6eb2bbb3a 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 73a055902..4cd09d230 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,9 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,7 +168,7 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 };
 
 static void *ctrl_thread_init(void *arg)
@@ -184,9 +183,9 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
@@ -194,8 +193,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -211,9 +210,9 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->start_routine = start_routine;
 	params->arg = arg;
 
-	pthread_barrier_init(&params->configured, NULL, 2);
+	rte_thread_barrier_init(&params->configured, 2);
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, params);
 	if (ret != 0) {
 		free(params);
 		return -ret;
@@ -226,26 +225,26 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, sizeof(*cpuset), cpuset);
 	if (ret)
 		goto fail;
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
 	return 0;
 
 fail:
-	if (PTHREAD_BARRIER_SERIAL_THREAD ==
-	    pthread_barrier_wait(&params->configured)) {
-		pthread_barrier_destroy(&params->configured);
+	if (RTE_THREAD_BARRIER_SERIAL_THREAD ==
+	    rte_thread_barrier_wait(&params->configured)) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
-	pthread_cancel(*thread);
-	pthread_join(*thread, NULL);
+	rte_thread_cancel(*thread);
+	rte_thread_join(*thread, NULL);
 	return -ret;
 }
 
@@ -266,7 +265,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), sizeof(cpuset),
 			&cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 24e27387b..6df4a0127 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b8a0d2002..d5a6abe9a 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index c7101b32d..fdc3a2cfe 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 70bd854fe..4cd4e8e70 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
 	'rte_random.c',
 	'rte_reciprocal.c',
 	'rte_service.c',
+	'rte_thread.c',
 	'rte_version.c',
 )
 
diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c
index 62320d610..21a4a977b 100644
--- a/lib/librte_eal/freebsd/eal.c
+++ b/lib/librte_eal/freebsd/eal.c
@@ -663,7 +663,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -686,7 +686,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -850,7 +850,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,6 +873,21 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -878,8 +901,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -889,10 +914,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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_alarm.c b/lib/librte_eal/freebsd/eal_alarm.c
index c38b2e04f..e5d7b130b 100644
--- a/lib/librte_eal/freebsd/eal_alarm.c
+++ b/lib/librte_eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/freebsd/eal_interrupts.c b/lib/librte_eal/freebsd/eal_interrupts.c
index 72eeacbc1..de5d2b733 100644
--- a/lib/librte_eal/freebsd/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -725,5 +725,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c
index 1dce9b04f..082a66917 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 3969cf4ac..0b6feb377 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
 	'rte_string_fns.h',
 	'rte_tailq.h',
 	'rte_thread.h',
+	'rte_thread_types.h',
 	'rte_time.h',
 	'rte_trace.h',
 	'rte_trace_point.h',
diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h
index 0fe0bd839..f895ef8ff 100644
--- a/lib/librte_eal/include/rte_lcore.h
+++ b/lib/librte_eal/include/rte_lcore.h
@@ -370,7 +370,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -387,7 +387,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -436,8 +436,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/librte_eal/include/rte_per_lcore.h b/lib/librte_eal/include/rte_per_lcore.h
index eaedf0cb3..025d97f96 100644
--- a/lib/librte_eal/include/rte_per_lcore.h
+++ b/lib/librte_eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c
index 9ffb4b331..419d9599f 100644
--- a/lib/librte_eal/linux/eal.c
+++ b/lib/librte_eal/linux/eal.c
@@ -958,7 +958,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -986,7 +986,7 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1214,7 +1214,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1228,6 +1236,23 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, (uintptr_t)thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1241,9 +1266,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1255,11 +1282,6 @@ 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_alarm.c b/lib/librte_eal/linux/eal_alarm.c
index 3252c6fa5..fef22a347 100644
--- a/lib/librte_eal/linux/eal_alarm.c
+++ b/lib/librte_eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/linux/eal_interrupts.c b/lib/librte_eal/linux/eal_interrupts.c
index 1dd994bd1..bc38055b8 100644
--- a/lib/librte_eal/linux/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1558,5 +1558,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c
index 83c2034b9..bd447d6a2 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -164,7 +164,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/lib/librte_eal/linux/eal_timer.c b/lib/librte_eal/linux/eal_timer.c
index 7cf15caba..b4099a0aa 100644
--- a/lib/librte_eal/linux/eal_timer.c
+++ b/lib/librte_eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index 474cf123f..13ba059c2 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -329,6 +329,25 @@ EXPORTS
 	rte_thread_tls_key_delete
 	rte_thread_tls_value_get
 	rte_thread_tls_value_set
+	rte_thread_mutex_lock
+	rte_thread_mutex_unlock
+	rte_thread_mutex_init
+	rte_thread_mutex_destroy
+	rte_thread_create
+	rte_thread_set_affinity_by_id
+	rte_thread_get_affinity_by_id
+	rte_thread_set_priority
+	rte_thread_attr_init
+	rte_thread_attr_set_affinity
+	rte_thread_attr_get_affinity
+	rte_thread_attr_set_priority
+	rte_thread_join
+	rte_thread_self
+	rte_thread_equal
+	rte_thread_barrier_init
+	rte_thread_barrier_wait
+	rte_thread_barrier_destroy
+	rte_thread_cancel
 
 	rte_mem_lock
 	rte_mem_map
diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build
index 71221b84a..d3af6b6fe 100644
--- a/lib/librte_eal/unix/meson.build
+++ b/lib/librte_eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
 	'eal_file.c',
 	'eal_unix_memory.c',
 	'eal_unix_timer.c',
-	'rte_thread.c',
 )
diff --git a/lib/librte_eal/unix/rte_thread.c b/lib/librte_eal/unix/rte_thread.c
deleted file mode 100644
index 86ffeebc9..000000000
--- a/lib/librte_eal/unix/rte_thread.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_tls_key_delete(rte_tls_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_tls_value_set(rte_tls_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_tls_value_get(rte_tls_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index 756c60ed1..7656f8738 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -419,6 +419,27 @@ EXPERIMENTAL {
 	rte_thread_tls_key_delete;
 	rte_thread_tls_value_get;
 	rte_thread_tls_value_set;
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 2fc3d6141..faaf00972 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -368,6 +368,28 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -384,7 +406,9 @@ rte_eal_init(int argc, char **argv)
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
index 3b8266d38..9839a1fed 100644
--- a/lib/librte_eal/windows/eal_interrupts.c
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -7,7 +7,7 @@
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +76,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -94,7 +94,7 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 
 	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread(%lu)", intr_thread);
 		return -ENOENT;
 	}
 
diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c
index 9c3f6d69f..5ed495562 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -60,11 +60,11 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index dc5dc8240..4b92b198c 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/librte_eal/windows/include/meson.build b/lib/librte_eal/windows/include/meson.build
index b3534b025..7d9b3393e 100644
--- a/lib/librte_eal/windows/include/meson.build
+++ b/lib/librte_eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
deleted file mode 100644
index 9aeab1fa7..000000000
--- a/lib/librte_eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/librte_eal/windows/include/sched.h b/lib/librte_eal/windows/include/sched.h
index fbe07f742..ac2c3d8fc 100644
--- a/lib/librte_eal/windows/include/sched.h
+++ b/lib/librte_eal/windows/include/sched.h
@@ -43,7 +43,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 42ff5c2d5..ffcddcd0c 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
 	'eal_timer.c',
 	'fnmatch.c',
 	'getopt.c',
-	'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'librte_eal/common/rte_thread.c'
+else
+	sources += 'librte_eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 6f514c388..3ae7687f8 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,7 +506,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -580,7 +580,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 918a34ed1..580108b95 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -5,7 +5,6 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
 #include <sys/types.h>
 
 /**
@@ -183,7 +182,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 241af6c4c..d096c3d57 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -223,14 +223,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index d8c635e99..33d8c7b54 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -121,7 +121,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1302,12 +1302,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 55d4856f9..b97774ccd 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index 3ab5cfdd6..ba58d849e 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 0169d3648..5f41d40ba 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,11 +1122,11 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 52ab93d1e..54db845da 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -646,7 +646,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -655,7 +655,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -663,12 +663,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 3b8c5d316..29f8df218 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -32,5 +32,7 @@ option('enable_trace_fp', type: 'boolean', value: false,
 	description: 'enable fast path trace points.')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false,
 	description: 'use HPET timer in EAL')
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-03-23  2:54       ` Stephen Hemminger
  2021-03-23 15:53         ` Tyler Retzlaff
  0 siblings, 1 reply; 290+ messages in thread
From: Stephen Hemminger @ 2021-03-23  2:54 UTC (permalink / raw)
  To: dev

On Mon, 22 Mar 2021 17:20:26 -0700
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> @@ -59,7 +92,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
>   *
>   * @return
>   *   On success, zero.
> - *   On failure, a negative number.
> + *   On failure, return a positive errno-style error number.
>   */

The common pattern in DPDK is to return a negative value for errors.
There is a tradeoff here, should the wrapper functions just mimic what
Posix API's do or not.

I prefer what this patch does; so users can just assume the rte_thread functions
all work exactly like the pthread versions.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions
  2021-03-23  2:54       ` Stephen Hemminger
@ 2021-03-23 15:53         ` Tyler Retzlaff
  0 siblings, 0 replies; 290+ messages in thread
From: Tyler Retzlaff @ 2021-03-23 15:53 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Mon, Mar 22, 2021 at 07:54:19PM -0700, Stephen Hemminger wrote:
> On Mon, 22 Mar 2021 17:20:26 -0700
> Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:
> 
> > @@ -59,7 +92,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
> >   *
> >   * @return
> >   *   On success, zero.
> > - *   On failure, a negative number.
> > + *   On failure, return a positive errno-style error number.
> >   */
> 
> The common pattern in DPDK is to return a negative value for errors.
> There is a tradeoff here, should the wrapper functions just mimic what
> Posix API's do or not.
> 
> I prefer what this patch does; so users can just assume the rte_thread functions
> all work exactly like the pthread versions.

yes, there was concern here that suddenly applying sign to errno
returned by an rte function that almost looks like a pthread function
will lead to a lot of misuse / confusion.

if this were to be changed at all i would suggest adopting more
consistently the use of rv = -1 and rte_errno set to indicate the error.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading
  2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                       ` (9 preceding siblings ...)
  2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-03-25  3:46     ` Narcisa Ana Maria Vasile
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                         ` (9 more replies)
  10 siblings, 10 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:46 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application. The two options above are available:

 --thread-prio normal
 --thread-prio realtime
 
Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  windows/eal: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +--
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |  36 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 +-
 lib/librte_eal/common/eal_common_thread.c     |  43 +-
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_internal_cfg.h      |   2 +
 lib/librte_eal/common/eal_options.h           |   2 +
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +-
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/common/rte_thread.c            | 342 ++++++++++++
 lib/librte_eal/freebsd/eal.c                  |  37 +-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/include/rte_thread.h           | 333 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/linux/eal.c                    |  42 +-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  19 +
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  86 ---
 lib/librte_eal/version.map                    |  21 +
 lib/librte_eal/windows/eal.c                  |  26 +-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_lcore.c            | 170 ++++--
 lib/librte_eal/windows/eal_thread.c           |  24 +-
 lib/librte_eal/windows/eal_windows.h          |  20 +-
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 -------
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_eal/windows/rte_thread.c           | 516 +++++++++++++++++-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 +-
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++---
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2039 insertions(+), 911 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 01/10] eal: add thread id and simple thread functions
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
@ 2021-03-25  3:46       ` Narcisa Ana Maria Vasile
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                         ` (8 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:46 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add the thread identifier type.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 101 ++++++++++++++++++
 lib/librte_eal/include/rte_thread.h           |  39 ++++++-
 lib/librte_eal/include/rte_thread_types.h     |  12 +++
 .../include/rte_windows_thread_types.h        |  12 +++
 lib/librte_eal/windows/rte_thread.c           |  13 +++
 5 files changed, 174 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
new file mode 100644
index 000000000..9b5cee890
--- /dev/null
+++ b/lib/librte_eal/common/rte_thread.c
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return pthread_self();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1, t2);
+}
+
+int
+rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_tls_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_tls_key_delete(rte_tls_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_tls_value_set(rte_tls_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_tls_value_get(rte_tls_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index ac5a89b1a..f7d398a22 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_os.h>
@@ -20,6 +21,13 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -27,6 +35,31 @@ typedef struct eal_tls_key *rte_tls_key;
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
@@ -63,7 +96,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -77,7 +110,7 @@ int rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *));
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_tls_key_delete(rte_tls_key key);
@@ -92,7 +125,7 @@ int rte_thread_tls_key_delete(rte_tls_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_tls_value_set(rte_tls_key key, const void *value);
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
new file mode 100644
index 000000000..19fb85e38
--- /dev/null
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+typedef pthread_t                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 000000000..ebd3d9e8f
--- /dev/null
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+typedef DWORD                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 2e2ab2917..43c09b2f3 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,18 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1 == t2 ? 1 : 0;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 02/10] eal: add thread attributes
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-03-25  3:46       ` Narcisa Ana Maria Vasile
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                         ` (7 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:46 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority

Implement functions for managing thread attributes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 53 ++++++++++++
 lib/librte_eal/include/rte_thread.h           | 82 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/librte_eal/windows/rte_thread.c           | 56 +++++++++++++
 5 files changed, 197 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 9b5cee890..b21eac0e2 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,59 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index f7d398a22..463357a1d 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -28,6 +28,19 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,
+	/*
+	 * This enum can be extended to allow more priority levels.
+	 */
+};
+
+typedef struct {
+	enum rte_thread_priority priority;
+	rte_cpuset_t cpuset;
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -60,6 +73,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr;
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+				 enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 19fb85e38..a884daf17 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 typedef pthread_t                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index ebd3d9e8f..8cb4b3856 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 typedef DWORD                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 43c09b2f3..d0294d179 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -24,6 +24,62 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to init thread attributes, invalid parameter\n");
+		return EINVAL;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-03-25  3:46       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                         ` (6 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:46 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/windows/rte_thread.c | 59 ++++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 9 deletions(-)

diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index d0294d179..c948b2c5e 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -12,6 +12,47 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int rte_thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+
+	default:
+		return EINVAL;
+	}
+
+	return EINVAL;
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -87,13 +128,13 @@ rte_thread_tls_key_create(rte_tls_key *key,
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
 		RTE_LOG_WIN32_ERR("TlsAlloc()");
 		free(*key);
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -101,14 +142,14 @@ rte_thread_tls_key_create(rte_tls_key *key,
 int
 rte_thread_tls_key_delete(rte_tls_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
 		RTE_LOG_WIN32_ERR("TlsFree()");
 		free(key);
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	free(key);
 	return 0;
@@ -119,15 +160,15 @@ rte_thread_tls_value_set(rte_tls_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
 		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -137,7 +178,7 @@ rte_thread_tls_value_get(rte_tls_key key)
 {
 	void *output;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 04/10] eal: implement functions for thread affinity management
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (2 preceding siblings ...)
  2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                         ` (5 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c   |  13 ++
 lib/librte_eal/include/rte_thread.h  |  41 +++++++
 lib/librte_eal/windows/eal_lcore.c   | 170 +++++++++++++++++++--------
 lib/librte_eal/windows/eal_windows.h |  10 ++
 lib/librte_eal/windows/rte_thread.c  | 132 ++++++++++++++++++++-
 5 files changed, 318 insertions(+), 48 deletions(-)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index b21eac0e2..9df98263e 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,19 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id, cpuset_size, cpuset);
+}
+
+int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 463357a1d..2e54b1da3 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -73,6 +73,47 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset_size
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset_size
+ *    Size of the cpu set.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
index a85149be9..023c5c895 100644
--- a/lib/librte_eal/windows/eal_lcore.c
+++ b/lib/librte_eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -28,13 +27,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -48,13 +49,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -79,57 +178,27 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
-		}
+		if (eal_check_for_duplicate_numa(info))
+			break;
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -139,7 +208,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -165,3 +234,12 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	if (cpu_index < CPU_SETSIZE)
+		return &cpu_map.cpus[cpu_index];
+
+	return NULL;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index 478accc1b..dc5dc8240 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index c948b2c5e..865b1b781 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -4,9 +4,9 @@
  */
 
 #include <rte_common.h>
-#include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -65,6 +65,134 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+			    size_t cpuset_size,
+			    const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 05/10] eal: implement thread priority management functions
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (3 preceding siblings ...)
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                         ` (4 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 25 ++++++++++
 lib/librte_eal/include/rte_thread.h | 17 +++++++
 lib/librte_eal/windows/rte_thread.c | 76 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 9df98263e..9e0d710dd 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -42,6 +42,31 @@ int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
 	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
 }
 
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int policy;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+
+
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+		policy = SCHED_RR;
+		param.sched_priority = priority;
+	} else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+		policy = SCHED_OTHER;
+		param.sched_priority = priority;
+	} else {
+		RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+				    "Defaulting to priority 'normal'.\n");
+		policy = SCHED_OTHER;
+	}
+
+	return pthread_setschedparam(thread_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 2e54b1da3..999c6d71d 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -114,6 +114,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 				  rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 865b1b781..3fb283ecb 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -193,6 +193,82 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	DWORD priority_class = NORMAL_PRIORITY_CLASS;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	switch (priority) {
+
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		priority_class = REALTIME_PRIORITY_CLASS;
+		break;
+
+	case RTE_THREAD_PRIORITY_NORMAL:
+	/* FALLTHROUGH */
+	default:
+		priority_class = NORMAL_PRIORITY_CLASS;
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+		break;
+	}
+
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, priority)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 06/10] eal: add thread lifetime management
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (4 preceding siblings ...)
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                         ` (3 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 110 ++++++++++++++++++++++++
 lib/librte_eal/include/rte_thread.h |  53 ++++++++++++
 lib/librte_eal/windows/rte_thread.c | 125 ++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 9e0d710dd..7feaf55ee 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -120,6 +120,116 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(thread_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id);
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 999c6d71d..b51ea3ba0 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -200,6 +200,59 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 				 enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 3fb283ecb..c42f0ea93 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -325,6 +325,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+
+	thread_handle = CreateThread(NULL, 0,
+				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,
+				args, 0, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("CreateThread()");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = rte_thread_translate_win32_error(GetLastError());
+				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = rte_thread_translate_win32_error(GetLastError());
+			RTE_LOG_WIN32_ERR("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_tls_key_create(rte_tls_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 07/10] eal: implement functions for mutex management
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (5 preceding siblings ...)
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                         ` (2 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 24 ++++++++
 lib/librte_eal/include/rte_thread.h           | 55 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  1 +
 lib/librte_eal/windows/rte_thread.c           | 28 ++++++++++
 5 files changed, 111 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 7feaf55ee..6e0f970af 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -220,6 +220,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index b51ea3ba0..6710216d6 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -240,6 +240,61 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @param attr
+ *    Attributes for initialization of the mutex.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index a884daf17..37bc7af2b 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,9 +7,12 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
 #define EAL_THREAD_PRIORITY_NORMAL               0
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
 
 typedef pthread_t                       rte_thread_t;
+typedef pthread_mutex_t                 rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 8cb4b3856..47c6b2664 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -11,5 +11,6 @@
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
+typedef CRITICAL_SECTION            rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index c42f0ea93..8a2c7691a 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -417,6 +417,34 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 08/10] eal: implement functions for thread barrier management
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (6 preceding siblings ...)
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 16 +++++++
 lib/librte_eal/include/rte_thread.h           | 46 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  2 +
 .../include/rte_windows_thread_types.h        |  3 ++
 lib/librte_eal/windows/rte_thread.c           | 27 +++++++++++
 5 files changed, 94 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 6e0f970af..0295bf874 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -244,6 +244,22 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	return pthread_barrier_init(barrier, NULL, count);
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_wait(barrier);
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_destroy(barrier);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 6710216d6..159c440a2 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -295,6 +295,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 37bc7af2b..b055bbf67 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
 #define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
 
 #define EAL_THREAD_PRIORITY_NORMAL               0
@@ -14,5 +15,6 @@
 
 typedef pthread_t                       rte_thread_t;
 typedef pthread_mutex_t                 rte_thread_mutex_t;
+typedef pthread_barrier_t               rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 47c6b2664..b6209e6eb 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,10 +7,13 @@
 
 #include <rte_windows.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
+
 #define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
 typedef CRITICAL_SECTION            rte_thread_mutex_t;
+typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 8a2c7691a..0d7cae254 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -445,6 +445,33 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+
+	if (!InitializeSynchronizationBarrier(barrier, count, -1)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("InitializeSynchronizationBarrier()");
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return EnterSynchronizationBarrier(barrier,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	DeleteSynchronizationBarrier(barrier);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 09/10] eal: add EAL argument for setting thread priority
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (7 preceding siblings ...)
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can select the thread priority to be either 'normal'
or 'critical':
--thread-prio normal
--thread-prio realtime

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/eal_common_options.c | 28 +++++++++++++++++++++-
 lib/librte_eal/common/eal_internal_cfg.h   |  2 ++
 lib/librte_eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 622c7bc42..287a89a75 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -106,6 +106,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1383,6 +1384,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1796,7 +1815,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2059,6 +2084,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 51dbe86e2..7ab1d0008 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -93,6 +93,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 7b348e707..9f5b209f6 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v3 10/10] Enable the new EAL thread API
  2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                         ` (8 preceding siblings ...)
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-25  3:47       ` Narcisa Ana Maria Vasile
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  9 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-25  3:47 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +--
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 ++--
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +++----
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |   8 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 ++---
 lib/librte_eal/common/eal_common_thread.c     |  43 ++--
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +--
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/freebsd/eal.c                  |  37 +++-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/linux/eal.c                    |  42 +++-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  19 ++
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  86 --------
 lib/librte_eal/version.map                    |  21 ++
 lib/librte_eal/windows/eal.c                  |  26 ++-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_thread.c           |  24 +--
 lib/librte_eal/windows/eal_windows.h          |  10 -
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------------------
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 ++--
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++++++------
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 658 insertions(+), 850 deletions(-)
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index 27f1b1c0e..ff284335a 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 #endif
 #endif
 
@@ -127,7 +127,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
-		pthread_create(&thread, NULL, &send_pkts, NULL);
+		rte_thread_create(&thread, NULL, &send_pkts, NULL);
 #endif
 #endif
 
@@ -137,7 +137,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fc..c507e423e 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a..3d9663f5e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d06..ce79d9c17 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 66a2edcc4..8db5bd725 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -258,6 +258,10 @@ else # for 32-bit we need smaller reserved memory areas
 	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da..a9e6013ff 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,11 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a..dc5f02bec 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681c..6d2d10cdf 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1..c826ad0c1 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -92,10 +92,10 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index ec3c23751..d2bda960f 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -73,7 +73,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -833,9 +833,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -855,13 +855,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb/pf/base/dlb_osdep.h b/drivers/event/dlb/pf/base/dlb_osdep.h
index dee20660e..cc22b85d6 100644
--- a/drivers/event/dlb/pf/base/dlb_osdep.h
+++ b/drivers/event/dlb/pf/base/dlb_osdep.h
@@ -208,7 +208,7 @@ static void *dlb_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb_hw *hw)
 {
 	struct dlb_dev *dlb_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb_dev = container_of(hw, struct dlb_dev, hw);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index aa101a49a..b002dc774 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index a64fef1cf..355f98534 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -179,7 +179,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -670,7 +670,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -681,7 +681,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -719,7 +719,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -745,7 +745,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -774,9 +774,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -942,9 +942,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index ef650a465..89d6b2bb4 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -618,12 +618,12 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
 		 */
-		if (pthread_create(&thread, NULL, delay_pg_start, ark)) {
+		if (rte_thread_create(&thread, NULL, delay_pg_start, ark)) {
 			ARK_PMD_LOG(ERR, "Could not create pktgen "
 				    "starter thread\n");
 			return -1;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f..96b7da3ac 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f32..93e41aa26 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405..a6f576dab 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b..197c72290 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876..e6f252e09 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729f..cfd436fa6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12..c17f9a8b9 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695a..5f3d9b360 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec19..1e1d6358d 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index de1b4af91..ef9be3847 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -533,8 +533,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -693,7 +693,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -747,18 +747,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -944,10 +944,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3..a50511047 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index f1dd40591..340608b60 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1043,7 +1043,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1053,20 +1053,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1443,14 +1443,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1532,13 +1532,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1571,14 +1571,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4066,7 +4066,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4074,7 +4074,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4244,7 +4244,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4259,7 +4259,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5048,25 +5048,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5833,14 +5833,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d..e1d980cf9 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index d94874578..472e6fead 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef9..455d83bef 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061..88d64d703 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd683..26c3e7551 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea..cb6bbcad6 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83..f06bd2b27 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2..1115afa81 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 932600d05..d8305f9ea 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -433,7 +433,7 @@ struct hns3_hw {
 	struct hns3_cmq cmq;
 	struct hns3_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hns3_mbx_arq_ring arq;         /* mailbox async rx queue */
-	pthread_t irq_thread_id;
+	rte_thread_t irq_thread_id;
 	struct hns3_mac mac;
 	unsigned int secondary_cnt; /* Number of secondary processes init'd. */
 	struct hns3_tqp_stats tqp_stats;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index fd20c522d..d78b45866 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1107,7 +1107,7 @@ hns3vf_interrupt_handler(void *param)
 	uint32_t clearval;
 
 	if (hw->irq_thread_id == 0)
-		hw->irq_thread_id = pthread_self();
+		hw->irq_thread_id = rte_thread_self();
 
 	/* Disable interrupt */
 	hns3vf_disable_irq0(hw);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 61d15845e..34d2458b1 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -101,7 +101,7 @@ hns3_get_mbx_resp(struct hns3_hw *hw, uint16_t code0, uint16_t code1,
 		 * Sending mbox in the interrupt thread cannot wait for the
 		 * response, so polling the mbox response on the irq thread.
 		 */
-		if (pthread_equal(hw->irq_thread_id, pthread_self())) {
+		if (rte_thread_equal(hw->irq_thread_id, rte_thread_self())) {
 			in_irq = true;
 			hns3_poll_all_sync_msg();
 		} else {
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 476fd4906..66bc7d683 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -152,7 +152,7 @@ static void
 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 {
 	struct ice_dcf_reset_event_param *param;
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
@@ -165,7 +165,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 	param->vfr = vfr;
 	param->vf_id = vf_id;
 
-	ret = pthread_create(&thread, NULL,
+	ret = rte_thread_create(&thread, NULL,
 			     ice_dcf_vsi_update_service_handler, param);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling");
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 856d21ef9..aa55e6fc0 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 8a9a21e7c..fcd80fbb6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4148,7 +4148,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	pthread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca2..272fdcfb8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549..3518b913e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 5e3ae9f10..21689c596 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2349,7 +2349,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index abd7ff70d..57645aed1 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -181,7 +181,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -884,7 +884,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1010,11 +1010,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1046,7 +1046,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1077,7 +1077,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1108,11 +1108,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2234,7 +2234,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 14043b68d..40e5bc76c 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -632,7 +632,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index e8d632ad2..2a149f5bf 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -904,7 +904,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -920,7 +920,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -947,7 +947,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -955,7 +955,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index 2cc02df32..dce2a6fe6 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_tls_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_tls_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 6f3927614..956e92d68 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -226,7 +226,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b539928..f0cb71c93 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8..1004ec289 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 1b54d55bd..2052d03a3 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -142,7 +142,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -160,7 +160,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -184,7 +184,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -205,12 +205,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -225,7 +225,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -248,11 +248,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -379,7 +379,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -404,7 +404,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -490,7 +490,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -795,13 +795,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -811,7 +811,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -836,7 +836,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 8a62f7ea7..db393e55b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -56,7 +56,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 05d79bfcc..6f97695e0 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -526,7 +526,7 @@ ifpga_monitor_start_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 0) {
-		ret = pthread_create(&ifpga_monitor_start_thread,
+		ret = rte_thread_create(&ifpga_monitor_start_thread,
 			NULL,
 			ifpga_rawdev_gsd_handle, NULL);
 		if (ret) {
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 39237aecf..6ff8dd123 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -50,7 +50,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -77,7 +77,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -87,7 +87,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -96,7 +96,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -110,7 +110,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -120,7 +120,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -496,7 +496,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, notify_relay,
+	ret = rte_thread_create(&internal->tid, NULL, notify_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create notify relay pthread.");
@@ -508,11 +508,9 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -799,7 +797,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, vring_relay,
+	ret = rte_thread_create(&internal->tid, NULL, vring_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create ring relay pthread.");
@@ -811,11 +809,9 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -1245,9 +1241,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1285,9 +1281,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 898e50f80..bcb744f5b 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -764,10 +764,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -798,7 +798,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -807,7 +807,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -816,7 +816,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index d93b430c9..568b84c3f 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 404e135d5..ebb53f4b1 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -247,17 +247,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -281,13 +281,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -297,7 +297,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -313,7 +313,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -332,7 +332,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -347,13 +347,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -369,7 +369,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -415,7 +415,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -502,47 +502,39 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+		rte_thread_attr_init(&attr);
+		CPU_ZERO(&cpuset);
+		if (priv->event_core != -1)
+			CPU_SET(priv->event_core, &cpuset);
+		else
+			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr,
+					RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
 			return -1;
 		}
-		CPU_ZERO(&cpuset);
-		if (priv->event_core != -1)
-			CPU_SET(priv->event_core, &cpuset);
-		else
-			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_setaffinity_np(priv->timer_tid,
-					     sizeof(cpuset), &cpuset);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread affinity.");
-			goto error;
-		}
 		snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
 		ret = pthread_setname_np(priv->timer_tid, name);
 		if (ret) {
@@ -569,7 +561,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -586,8 +577,8 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
 	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
 	priv->timer_tid = 0;
 }
diff --git a/examples/kni/main.c b/examples/kni/main.c
index fe93b8618..d29cbf7ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 2ca7d98c5..c3b2273ef 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1635,7 +1635,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index 7ea60863d..5ea1b45ac 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, sizeof(cpu_set_t), &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring;
 
@@ -672,7 +672,7 @@ new_device(int vid)
 	/* start polling vring */
 	worker_thread_status = WORKER_STATE_START;
 	fprintf(stdout, "New Device %s, Device ID %d\n", path, vid);
-	if (pthread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
+	if (rte_thread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
 		fprintf(stderr, "Worker Thread Started Failed\n");
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 287a89a75..839d837f2 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -1843,8 +1843,8 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t),  &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1872,8 +1872,8 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					  sizeof(rte_cpuset_t), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
index 6d1af3c0e..6eb2bbb3a 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 73a055902..4cd09d230 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,9 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,7 +168,7 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 };
 
 static void *ctrl_thread_init(void *arg)
@@ -184,9 +183,9 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
@@ -194,8 +193,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -211,9 +210,9 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->start_routine = start_routine;
 	params->arg = arg;
 
-	pthread_barrier_init(&params->configured, NULL, 2);
+	rte_thread_barrier_init(&params->configured, 2);
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, params);
 	if (ret != 0) {
 		free(params);
 		return -ret;
@@ -226,26 +225,26 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, sizeof(*cpuset), cpuset);
 	if (ret)
 		goto fail;
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
 	return 0;
 
 fail:
-	if (PTHREAD_BARRIER_SERIAL_THREAD ==
-	    pthread_barrier_wait(&params->configured)) {
-		pthread_barrier_destroy(&params->configured);
+	if (RTE_THREAD_BARRIER_SERIAL_THREAD ==
+	    rte_thread_barrier_wait(&params->configured)) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
-	pthread_cancel(*thread);
-	pthread_join(*thread, NULL);
+	rte_thread_cancel(*thread);
+	rte_thread_join(*thread, NULL);
 	return -ret;
 }
 
@@ -266,7 +265,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), sizeof(cpuset),
 			&cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 24e27387b..6df4a0127 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b8a0d2002..d5a6abe9a 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index c7101b32d..fdc3a2cfe 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 70bd854fe..4cd4e8e70 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
 	'rte_random.c',
 	'rte_reciprocal.c',
 	'rte_service.c',
+	'rte_thread.c',
 	'rte_version.c',
 )
 
diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c
index 62320d610..21a4a977b 100644
--- a/lib/librte_eal/freebsd/eal.c
+++ b/lib/librte_eal/freebsd/eal.c
@@ -663,7 +663,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -686,7 +686,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -850,7 +850,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,6 +873,21 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -878,8 +901,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -889,10 +914,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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_alarm.c b/lib/librte_eal/freebsd/eal_alarm.c
index c38b2e04f..e5d7b130b 100644
--- a/lib/librte_eal/freebsd/eal_alarm.c
+++ b/lib/librte_eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/freebsd/eal_interrupts.c b/lib/librte_eal/freebsd/eal_interrupts.c
index 72eeacbc1..de5d2b733 100644
--- a/lib/librte_eal/freebsd/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -725,5 +725,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c
index 1dce9b04f..082a66917 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 3969cf4ac..0b6feb377 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
 	'rte_string_fns.h',
 	'rte_tailq.h',
 	'rte_thread.h',
+	'rte_thread_types.h',
 	'rte_time.h',
 	'rte_trace.h',
 	'rte_trace_point.h',
diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h
index 1550b75da..d5e004105 100644
--- a/lib/librte_eal/include/rte_lcore.h
+++ b/lib/librte_eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/librte_eal/include/rte_per_lcore.h b/lib/librte_eal/include/rte_per_lcore.h
index eaedf0cb3..025d97f96 100644
--- a/lib/librte_eal/include/rte_per_lcore.h
+++ b/lib/librte_eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c
index 9ffb4b331..419d9599f 100644
--- a/lib/librte_eal/linux/eal.c
+++ b/lib/librte_eal/linux/eal.c
@@ -958,7 +958,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -986,7 +986,7 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1214,7 +1214,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1228,6 +1236,23 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, (uintptr_t)thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1241,9 +1266,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1255,11 +1282,6 @@ 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_alarm.c b/lib/librte_eal/linux/eal_alarm.c
index 3252c6fa5..fef22a347 100644
--- a/lib/librte_eal/linux/eal_alarm.c
+++ b/lib/librte_eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/linux/eal_interrupts.c b/lib/librte_eal/linux/eal_interrupts.c
index 1dd994bd1..bc38055b8 100644
--- a/lib/librte_eal/linux/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1558,5 +1558,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c
index 83c2034b9..bd447d6a2 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -164,7 +164,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/lib/librte_eal/linux/eal_timer.c b/lib/librte_eal/linux/eal_timer.c
index 7cf15caba..b4099a0aa 100644
--- a/lib/librte_eal/linux/eal_timer.c
+++ b/lib/librte_eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index 474cf123f..13ba059c2 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -329,6 +329,25 @@ EXPORTS
 	rte_thread_tls_key_delete
 	rte_thread_tls_value_get
 	rte_thread_tls_value_set
+	rte_thread_mutex_lock
+	rte_thread_mutex_unlock
+	rte_thread_mutex_init
+	rte_thread_mutex_destroy
+	rte_thread_create
+	rte_thread_set_affinity_by_id
+	rte_thread_get_affinity_by_id
+	rte_thread_set_priority
+	rte_thread_attr_init
+	rte_thread_attr_set_affinity
+	rte_thread_attr_get_affinity
+	rte_thread_attr_set_priority
+	rte_thread_join
+	rte_thread_self
+	rte_thread_equal
+	rte_thread_barrier_init
+	rte_thread_barrier_wait
+	rte_thread_barrier_destroy
+	rte_thread_cancel
 
 	rte_mem_lock
 	rte_mem_map
diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build
index 71221b84a..d3af6b6fe 100644
--- a/lib/librte_eal/unix/meson.build
+++ b/lib/librte_eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
 	'eal_file.c',
 	'eal_unix_memory.c',
 	'eal_unix_timer.c',
-	'rte_thread.c',
 )
diff --git a/lib/librte_eal/unix/rte_thread.c b/lib/librte_eal/unix/rte_thread.c
deleted file mode 100644
index 86ffeebc9..000000000
--- a/lib/librte_eal/unix/rte_thread.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_tls_key_create(rte_tls_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_tls_key_delete(rte_tls_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_tls_value_set(rte_tls_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_tls_value_get(rte_tls_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index 48a2b55d5..482e73115 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,6 +421,27 @@ EXPERIMENTAL {
 	rte_version_release;
 	rte_version_suffix;
 	rte_version_year;
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 2fc3d6141..faaf00972 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -368,6 +368,28 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -384,7 +406,9 @@ rte_eal_init(int argc, char **argv)
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
index 3b8266d38..9839a1fed 100644
--- a/lib/librte_eal/windows/eal_interrupts.c
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -7,7 +7,7 @@
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +76,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -94,7 +94,7 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 
 	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread(%lu)", intr_thread);
 		return -ENOENT;
 	}
 
diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c
index 9c3f6d69f..5ed495562 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -60,11 +60,11 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index dc5dc8240..4b92b198c 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/librte_eal/windows/include/meson.build b/lib/librte_eal/windows/include/meson.build
index b3534b025..7d9b3393e 100644
--- a/lib/librte_eal/windows/include/meson.build
+++ b/lib/librte_eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
deleted file mode 100644
index 9aeab1fa7..000000000
--- a/lib/librte_eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/librte_eal/windows/include/sched.h b/lib/librte_eal/windows/include/sched.h
index ff572b5dc..8f0b3cb71 100644
--- a/lib/librte_eal/windows/include/sched.h
+++ b/lib/librte_eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 42ff5c2d5..ffcddcd0c 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
 	'eal_timer.c',
 	'fnmatch.c',
 	'getopt.c',
-	'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'librte_eal/common/rte_thread.c'
+else
+	sources += 'librte_eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3059aa55b..72db655f6 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,7 +506,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -580,7 +580,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 918a34ed1..580108b95 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -5,7 +5,6 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
 #include <sys/types.h>
 
 /**
@@ -183,7 +182,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 241af6c4c..d096c3d57 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -223,14 +223,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index d8c635e99..33d8c7b54 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -121,7 +121,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1302,12 +1302,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 55d4856f9..b97774ccd 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index 3ab5cfdd6..ba58d849e 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 0169d3648..5f41d40ba 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,11 +1122,11 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 52ab93d1e..54db845da 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -646,7 +646,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -655,7 +655,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -663,12 +663,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 3b8c5d316..29f8df218 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -32,5 +32,7 @@ option('enable_trace_fp', type: 'boolean', value: false,
 	description: 'enable fast path trace points.')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false,
 	description: 'use HPET timer in EAL')
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading
  2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-03-26 23:52         ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                             ` (9 more replies)
  0 siblings, 10 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application. The two options above are available:

 --thread-prio normal
 --thread-prio realtime
 
Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c


Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  windows/eal: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +--
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |  36 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 +-
 lib/librte_eal/common/eal_common_thread.c     |  43 +-
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_internal_cfg.h      |   2 +
 lib/librte_eal/common/eal_options.h           |   2 +
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +-
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/common/rte_thread.c            | 342 ++++++++++++
 lib/librte_eal/freebsd/eal.c                  |  37 +-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/include/rte_thread.h           | 337 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/linux/eal.c                    |  42 +-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  20 +
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  92 ---
 lib/librte_eal/version.map                    |  21 +
 lib/librte_eal/windows/eal.c                  |  26 +-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_lcore.c            | 170 ++++--
 lib/librte_eal/windows/eal_thread.c           |  24 +-
 lib/librte_eal/windows/eal_windows.h          |  20 +-
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 -------
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_eal/windows/rte_thread.c           | 522 +++++++++++++++++-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 +-
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 +++--
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2038 insertions(+), 929 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 01/10] eal: add thread id and simple thread functions
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                             ` (8 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add the thread identifier type.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 101 ++++++++++++++++++
 lib/librte_eal/include/rte_thread.h           |  45 ++++++--
 lib/librte_eal/include/rte_thread_types.h     |  12 +++
 .../include/rte_windows_thread_types.h        |  12 +++
 lib/librte_eal/windows/rte_thread.c           |  13 +++
 5 files changed, 174 insertions(+), 9 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
new file mode 100644
index 000000000..5ec382949
--- /dev/null
+++ b/lib/librte_eal/common/rte_thread.c
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return pthread_self();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1, t2);
+}
+
+int
+rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_thread_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_key_delete(rte_thread_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_value_set(rte_thread_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_value_get(rte_thread_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 8be8ed8f3..cbc07f739 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_os.h>
@@ -20,6 +21,13 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -27,6 +35,31 @@ typedef struct eal_tls_key *rte_thread_key;
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
@@ -63,9 +96,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +111,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +126,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
new file mode 100644
index 000000000..19fb85e38
--- /dev/null
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+typedef pthread_t                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 000000000..ebd3d9e8f
--- /dev/null
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+typedef DWORD                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 667287c38..940d9c653 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,18 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1 == t2 ? 1 : 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 02/10] eal: add thread attributes
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                             ` (7 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority

Implement functions for managing thread attributes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 53 ++++++++++++
 lib/librte_eal/include/rte_thread.h           | 82 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/librte_eal/windows/rte_thread.c           | 56 +++++++++++++
 5 files changed, 197 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 5ec382949..0bd1b115d 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,59 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index cbc07f739..bfdd8e1b1 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -28,6 +28,19 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,
+	/*
+	 * This enum can be extended to allow more priority levels.
+	 */
+};
+
+typedef struct {
+	enum rte_thread_priority priority;
+	rte_cpuset_t cpuset;
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -60,6 +73,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr;
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+				 enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 19fb85e38..a884daf17 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 typedef pthread_t                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index ebd3d9e8f..8cb4b3856 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 typedef DWORD                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 940d9c653..b29336cbd 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -24,6 +24,62 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to init thread attributes, invalid parameter\n");
+		return EINVAL;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                             ` (6 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/windows/rte_thread.c | 65 ++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 15 deletions(-)

diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index b29336cbd..e9181b47f 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -12,6 +12,47 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int rte_thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+
+	default:
+		return EINVAL;
+	}
+
+	return EINVAL;
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -87,15 +128,13 @@ rte_thread_key_create(rte_thread_key *key,
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
 		RTE_LOG_WIN32_ERR("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -103,16 +142,14 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
 		RTE_LOG_WIN32_ERR("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	free(key);
 	return 0;
@@ -123,17 +160,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
 		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -143,7 +178,7 @@ rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 04/10] eal: implement functions for thread affinity management
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (2 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                             ` (5 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c   |  13 ++
 lib/librte_eal/include/rte_thread.h  |  41 +++++++
 lib/librte_eal/windows/eal_lcore.c   | 170 +++++++++++++++++++--------
 lib/librte_eal/windows/eal_windows.h |  10 ++
 lib/librte_eal/windows/rte_thread.c  | 132 ++++++++++++++++++++-
 5 files changed, 318 insertions(+), 48 deletions(-)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 0bd1b115d..4f93e3ff1 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,19 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id, cpuset_size, cpuset);
+}
+
+int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index bfdd8e1b1..ed8330f81 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -73,6 +73,47 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset_size
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset_size
+ *    Size of the cpu set.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
index a85149be9..023c5c895 100644
--- a/lib/librte_eal/windows/eal_lcore.c
+++ b/lib/librte_eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -28,13 +27,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -48,13 +49,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -79,57 +178,27 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
-		}
+		if (eal_check_for_duplicate_numa(info))
+			break;
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -139,7 +208,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -165,3 +234,12 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	if (cpu_index < CPU_SETSIZE)
+		return &cpu_map.cpus[cpu_index];
+
+	return NULL;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index 478accc1b..dc5dc8240 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index e9181b47f..d60a3ded5 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -4,9 +4,9 @@
  */
 
 #include <rte_common.h>
-#include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -65,6 +65,134 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+			    size_t cpuset_size,
+			    const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 05/10] eal: implement thread priority management functions
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (3 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                             ` (4 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 25 ++++++++++
 lib/librte_eal/include/rte_thread.h | 17 +++++++
 lib/librte_eal/windows/rte_thread.c | 76 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 4f93e3ff1..26c5b1f3c 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -42,6 +42,31 @@ int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
 	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
 }
 
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int policy;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+
+
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+		policy = SCHED_RR;
+		param.sched_priority = priority;
+	} else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+		policy = SCHED_OTHER;
+		param.sched_priority = priority;
+	} else {
+		RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+				    "Defaulting to priority 'normal'.\n");
+		policy = SCHED_OTHER;
+	}
+
+	return pthread_setschedparam(thread_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index ed8330f81..34948dd90 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -114,6 +114,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 				  rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index d60a3ded5..544aaf33d 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -193,6 +193,82 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	DWORD priority_class = NORMAL_PRIORITY_CLASS;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	switch (priority) {
+
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		priority_class = REALTIME_PRIORITY_CLASS;
+		break;
+
+	case RTE_THREAD_PRIORITY_NORMAL:
+	/* FALLTHROUGH */
+	default:
+		priority_class = NORMAL_PRIORITY_CLASS;
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+		break;
+	}
+
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, priority)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 06/10] eal: add thread lifetime management
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (4 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                             ` (3 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 110 ++++++++++++++++++++++++
 lib/librte_eal/include/rte_thread.h |  53 ++++++++++++
 lib/librte_eal/windows/rte_thread.c | 125 ++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 26c5b1f3c..29d38d193 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -120,6 +120,116 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(thread_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 34948dd90..24dc186f1 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -200,6 +200,59 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 				 enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 544aaf33d..85b11c5f5 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -325,6 +325,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+
+	thread_handle = CreateThread(NULL, 0,
+				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,
+				args, 0, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("CreateThread()");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = rte_thread_translate_win32_error(GetLastError());
+				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = rte_thread_translate_win32_error(GetLastError());
+			RTE_LOG_WIN32_ERR("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 07/10] eal: implement functions for mutex management
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (5 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                             ` (2 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 24 +++++++++
 lib/librte_eal/include/rte_thread.h           | 53 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 ++
 .../include/rte_windows_thread_types.h        |  1 +
 lib/librte_eal/windows/rte_thread.c           | 28 ++++++++++
 5 files changed, 109 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 29d38d193..8e963ed65 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -220,6 +220,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 24dc186f1..2b8d81005 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -240,6 +240,58 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
@@ -259,6 +311,7 @@ int rte_thread_cancel(rte_thread_t thread_id);
  *
  * @param cpusetp
  *   Pointer to CPU affinity to set.
+ *
  * @return
  *   On success, return 0; otherwise return -1;
  */
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index a884daf17..37bc7af2b 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,9 +7,12 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
 #define EAL_THREAD_PRIORITY_NORMAL               0
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
 
 typedef pthread_t                       rte_thread_t;
+typedef pthread_mutex_t                 rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 8cb4b3856..47c6b2664 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -11,5 +11,6 @@
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
+typedef CRITICAL_SECTION            rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 85b11c5f5..a26b8c08f 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -417,6 +417,34 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 08/10] eal: implement functions for thread barrier management
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (6 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 " Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 16 +++++++
 lib/librte_eal/include/rte_thread.h           | 46 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  2 +
 .../include/rte_windows_thread_types.h        |  3 ++
 lib/librte_eal/windows/rte_thread.c           | 27 +++++++++++
 5 files changed, 94 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 8e963ed65..d23d3b868 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -244,6 +244,22 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	return pthread_barrier_init(barrier, NULL, count);
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_wait(barrier);
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_destroy(barrier);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 2b8d81005..5b4da8053 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -292,6 +292,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 37bc7af2b..b055bbf67 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
 #define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
 
 #define EAL_THREAD_PRIORITY_NORMAL               0
@@ -14,5 +15,6 @@
 
 typedef pthread_t                       rte_thread_t;
 typedef pthread_mutex_t                 rte_thread_mutex_t;
+typedef pthread_barrier_t               rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 47c6b2664..b6209e6eb 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,10 +7,13 @@
 
 #include <rte_windows.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
+
 #define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
 typedef CRITICAL_SECTION            rte_thread_mutex_t;
+typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index a26b8c08f..c3c198663 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -445,6 +445,33 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+
+	if (!InitializeSynchronizationBarrier(barrier, count, -1)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("InitializeSynchronizationBarrier()");
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return EnterSynchronizationBarrier(barrier,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	DeleteSynchronizationBarrier(barrier);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (7 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  2021-03-27 16:04             ` Stephen Hemminger
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 " Narcisa Ana Maria Vasile
  9 siblings, 2 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can select the thread priority to be either 'normal'
or 'critical':
--thread-prio normal
--thread-prio realtime

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/eal_common_options.c | 28 +++++++++++++++++++++-
 lib/librte_eal/common/eal_internal_cfg.h   |  2 ++
 lib/librte_eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 622c7bc42..287a89a75 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -106,6 +106,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1383,6 +1384,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1796,7 +1815,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2059,6 +2084,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 51dbe86e2..7ab1d0008 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -93,6 +93,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 7b348e707..9f5b209f6 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v4 10/10] Enable the new EAL thread API
  2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                             ` (8 preceding siblings ...)
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-26 23:52           ` Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-26 23:52 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +--
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 ++--
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +++----
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |   8 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 ++---
 lib/librte_eal/common/eal_common_thread.c     |  43 ++--
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +--
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/freebsd/eal.c                  |  37 +++-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/linux/eal.c                    |  42 +++-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  20 ++
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  92 ---------
 lib/librte_eal/version.map                    |  21 ++
 lib/librte_eal/windows/eal.c                  |  26 ++-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_thread.c           |  24 +--
 lib/librte_eal/windows/eal_windows.h          |  10 -
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------------------
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 ++--
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++++++------
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 659 insertions(+), 856 deletions(-)
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index 27f1b1c0e..ff284335a 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 #endif
 #endif
 
@@ -127,7 +127,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
-		pthread_create(&thread, NULL, &send_pkts, NULL);
+		rte_thread_create(&thread, NULL, &send_pkts, NULL);
 #endif
 #endif
 
@@ -137,7 +137,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fc..c507e423e 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a..3d9663f5e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d06..ce79d9c17 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 66a2edcc4..8db5bd725 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -258,6 +258,10 @@ else # for 32-bit we need smaller reserved memory areas
 	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da..a9e6013ff 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,11 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a..dc5f02bec 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681c..6d2d10cdf 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1..c826ad0c1 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -92,10 +92,10 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index ec3c23751..d2bda960f 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -73,7 +73,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -833,9 +833,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -855,13 +855,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb/pf/base/dlb_osdep.h b/drivers/event/dlb/pf/base/dlb_osdep.h
index dee20660e..cc22b85d6 100644
--- a/drivers/event/dlb/pf/base/dlb_osdep.h
+++ b/drivers/event/dlb/pf/base/dlb_osdep.h
@@ -208,7 +208,7 @@ static void *dlb_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb_hw *hw)
 {
 	struct dlb_dev *dlb_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb_dev = container_of(hw, struct dlb_dev, hw);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index aa101a49a..b002dc774 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index a64fef1cf..355f98534 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -179,7 +179,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -670,7 +670,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -681,7 +681,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -719,7 +719,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -745,7 +745,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -774,9 +774,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -942,9 +942,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index ef650a465..89d6b2bb4 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -618,12 +618,12 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
 		 */
-		if (pthread_create(&thread, NULL, delay_pg_start, ark)) {
+		if (rte_thread_create(&thread, NULL, delay_pg_start, ark)) {
 			ARK_PMD_LOG(ERR, "Could not create pktgen "
 				    "starter thread\n");
 			return -1;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f..96b7da3ac 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f32..93e41aa26 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405..a6f576dab 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b..197c72290 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876..e6f252e09 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729f..cfd436fa6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12..c17f9a8b9 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695a..5f3d9b360 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec19..1e1d6358d 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index de1b4af91..ef9be3847 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -533,8 +533,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -693,7 +693,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -747,18 +747,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -944,10 +944,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3..a50511047 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index f1dd40591..340608b60 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1043,7 +1043,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1053,20 +1053,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1443,14 +1443,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1532,13 +1532,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1571,14 +1571,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4066,7 +4066,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4074,7 +4074,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4244,7 +4244,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4259,7 +4259,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5048,25 +5048,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5833,14 +5833,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d..e1d980cf9 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index d94874578..472e6fead 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef9..455d83bef 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061..88d64d703 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd683..26c3e7551 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea..cb6bbcad6 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83..f06bd2b27 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2..1115afa81 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 932600d05..d8305f9ea 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -433,7 +433,7 @@ struct hns3_hw {
 	struct hns3_cmq cmq;
 	struct hns3_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hns3_mbx_arq_ring arq;         /* mailbox async rx queue */
-	pthread_t irq_thread_id;
+	rte_thread_t irq_thread_id;
 	struct hns3_mac mac;
 	unsigned int secondary_cnt; /* Number of secondary processes init'd. */
 	struct hns3_tqp_stats tqp_stats;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index fd20c522d..d78b45866 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1107,7 +1107,7 @@ hns3vf_interrupt_handler(void *param)
 	uint32_t clearval;
 
 	if (hw->irq_thread_id == 0)
-		hw->irq_thread_id = pthread_self();
+		hw->irq_thread_id = rte_thread_self();
 
 	/* Disable interrupt */
 	hns3vf_disable_irq0(hw);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 61d15845e..34d2458b1 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -101,7 +101,7 @@ hns3_get_mbx_resp(struct hns3_hw *hw, uint16_t code0, uint16_t code1,
 		 * Sending mbox in the interrupt thread cannot wait for the
 		 * response, so polling the mbox response on the irq thread.
 		 */
-		if (pthread_equal(hw->irq_thread_id, pthread_self())) {
+		if (rte_thread_equal(hw->irq_thread_id, rte_thread_self())) {
 			in_irq = true;
 			hns3_poll_all_sync_msg();
 		} else {
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 476fd4906..66bc7d683 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -152,7 +152,7 @@ static void
 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 {
 	struct ice_dcf_reset_event_param *param;
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
@@ -165,7 +165,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 	param->vfr = vfr;
 	param->vf_id = vf_id;
 
-	ret = pthread_create(&thread, NULL,
+	ret = rte_thread_create(&thread, NULL,
 			     ice_dcf_vsi_update_service_handler, param);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling");
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 856d21ef9..aa55e6fc0 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 8a9a21e7c..fcd80fbb6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4148,7 +4148,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	pthread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca2..272fdcfb8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549..3518b913e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 5e3ae9f10..21689c596 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2349,7 +2349,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index abd7ff70d..57645aed1 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -181,7 +181,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -884,7 +884,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1010,11 +1010,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1046,7 +1046,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1077,7 +1077,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1108,11 +1108,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2234,7 +2234,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 14043b68d..40e5bc76c 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -632,7 +632,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index e8d632ad2..2a149f5bf 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -904,7 +904,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -920,7 +920,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -947,7 +947,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -955,7 +955,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index c4d579072..229bad3ea 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_thread_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 6f3927614..956e92d68 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -226,7 +226,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b539928..f0cb71c93 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8..1004ec289 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 1b54d55bd..2052d03a3 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -142,7 +142,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -160,7 +160,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -184,7 +184,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -205,12 +205,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -225,7 +225,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -248,11 +248,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -379,7 +379,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -404,7 +404,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -490,7 +490,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -795,13 +795,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -811,7 +811,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -836,7 +836,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 8a62f7ea7..db393e55b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -56,7 +56,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 05d79bfcc..6f97695e0 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -526,7 +526,7 @@ ifpga_monitor_start_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 0) {
-		ret = pthread_create(&ifpga_monitor_start_thread,
+		ret = rte_thread_create(&ifpga_monitor_start_thread,
 			NULL,
 			ifpga_rawdev_gsd_handle, NULL);
 		if (ret) {
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 39237aecf..6ff8dd123 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -50,7 +50,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -77,7 +77,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -87,7 +87,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -96,7 +96,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -110,7 +110,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -120,7 +120,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -496,7 +496,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, notify_relay,
+	ret = rte_thread_create(&internal->tid, NULL, notify_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create notify relay pthread.");
@@ -508,11 +508,9 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -799,7 +797,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, vring_relay,
+	ret = rte_thread_create(&internal->tid, NULL, vring_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create ring relay pthread.");
@@ -811,11 +809,9 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -1245,9 +1241,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1285,9 +1281,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 898e50f80..bcb744f5b 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -764,10 +764,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -798,7 +798,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -807,7 +807,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -816,7 +816,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index d93b430c9..568b84c3f 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 404e135d5..ebb53f4b1 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -247,17 +247,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -281,13 +281,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -297,7 +297,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -313,7 +313,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -332,7 +332,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -347,13 +347,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -369,7 +369,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -415,7 +415,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -502,47 +502,39 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+		rte_thread_attr_init(&attr);
+		CPU_ZERO(&cpuset);
+		if (priv->event_core != -1)
+			CPU_SET(priv->event_core, &cpuset);
+		else
+			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr,
+					RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
 			return -1;
 		}
-		CPU_ZERO(&cpuset);
-		if (priv->event_core != -1)
-			CPU_SET(priv->event_core, &cpuset);
-		else
-			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_setaffinity_np(priv->timer_tid,
-					     sizeof(cpuset), &cpuset);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread affinity.");
-			goto error;
-		}
 		snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
 		ret = pthread_setname_np(priv->timer_tid, name);
 		if (ret) {
@@ -569,7 +561,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -586,8 +577,8 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
 	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
 	priv->timer_tid = 0;
 }
diff --git a/examples/kni/main.c b/examples/kni/main.c
index fe93b8618..d29cbf7ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 2ca7d98c5..c3b2273ef 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1635,7 +1635,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index 7ea60863d..5ea1b45ac 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, sizeof(cpu_set_t), &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring;
 
@@ -672,7 +672,7 @@ new_device(int vid)
 	/* start polling vring */
 	worker_thread_status = WORKER_STATE_START;
 	fprintf(stdout, "New Device %s, Device ID %d\n", path, vid);
-	if (pthread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
+	if (rte_thread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
 		fprintf(stderr, "Worker Thread Started Failed\n");
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 287a89a75..839d837f2 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -1843,8 +1843,8 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t),  &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1872,8 +1872,8 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					  sizeof(rte_cpuset_t), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
index 6d1af3c0e..6eb2bbb3a 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 73a055902..4cd09d230 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,9 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,7 +168,7 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 };
 
 static void *ctrl_thread_init(void *arg)
@@ -184,9 +183,9 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
@@ -194,8 +193,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -211,9 +210,9 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->start_routine = start_routine;
 	params->arg = arg;
 
-	pthread_barrier_init(&params->configured, NULL, 2);
+	rte_thread_barrier_init(&params->configured, 2);
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, params);
 	if (ret != 0) {
 		free(params);
 		return -ret;
@@ -226,26 +225,26 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, sizeof(*cpuset), cpuset);
 	if (ret)
 		goto fail;
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
 	return 0;
 
 fail:
-	if (PTHREAD_BARRIER_SERIAL_THREAD ==
-	    pthread_barrier_wait(&params->configured)) {
-		pthread_barrier_destroy(&params->configured);
+	if (RTE_THREAD_BARRIER_SERIAL_THREAD ==
+	    rte_thread_barrier_wait(&params->configured)) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
-	pthread_cancel(*thread);
-	pthread_join(*thread, NULL);
+	rte_thread_cancel(*thread);
+	rte_thread_join(*thread, NULL);
 	return -ret;
 }
 
@@ -266,7 +265,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), sizeof(cpuset),
 			&cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 24e27387b..6df4a0127 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b8a0d2002..d5a6abe9a 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index c7101b32d..fdc3a2cfe 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 70bd854fe..4cd4e8e70 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
 	'rte_random.c',
 	'rte_reciprocal.c',
 	'rte_service.c',
+	'rte_thread.c',
 	'rte_version.c',
 )
 
diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c
index 32442e5ba..0960dc90e 100644
--- a/lib/librte_eal/freebsd/eal.c
+++ b/lib/librte_eal/freebsd/eal.c
@@ -663,7 +663,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -686,7 +686,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -850,7 +850,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,6 +873,21 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -878,8 +901,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -889,10 +914,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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_alarm.c b/lib/librte_eal/freebsd/eal_alarm.c
index c38b2e04f..e5d7b130b 100644
--- a/lib/librte_eal/freebsd/eal_alarm.c
+++ b/lib/librte_eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/freebsd/eal_interrupts.c b/lib/librte_eal/freebsd/eal_interrupts.c
index 72eeacbc1..de5d2b733 100644
--- a/lib/librte_eal/freebsd/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -725,5 +725,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c
index 1dce9b04f..082a66917 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 3969cf4ac..0b6feb377 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
 	'rte_string_fns.h',
 	'rte_tailq.h',
 	'rte_thread.h',
+	'rte_thread_types.h',
 	'rte_time.h',
 	'rte_trace.h',
 	'rte_trace_point.h',
diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h
index 1550b75da..d5e004105 100644
--- a/lib/librte_eal/include/rte_lcore.h
+++ b/lib/librte_eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/librte_eal/include/rte_per_lcore.h b/lib/librte_eal/include/rte_per_lcore.h
index eaedf0cb3..025d97f96 100644
--- a/lib/librte_eal/include/rte_per_lcore.h
+++ b/lib/librte_eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c
index abbb53774..76f2daa26 100644
--- a/lib/librte_eal/linux/eal.c
+++ b/lib/librte_eal/linux/eal.c
@@ -958,7 +958,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -986,7 +986,7 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1214,7 +1214,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1228,6 +1236,23 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, (uintptr_t)thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1241,9 +1266,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1255,11 +1282,6 @@ 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_alarm.c b/lib/librte_eal/linux/eal_alarm.c
index 3252c6fa5..fef22a347 100644
--- a/lib/librte_eal/linux/eal_alarm.c
+++ b/lib/librte_eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/linux/eal_interrupts.c b/lib/librte_eal/linux/eal_interrupts.c
index 1dd994bd1..bc38055b8 100644
--- a/lib/librte_eal/linux/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1558,5 +1558,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c
index 83c2034b9..bd447d6a2 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -164,7 +164,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/lib/librte_eal/linux/eal_timer.c b/lib/librte_eal/linux/eal_timer.c
index 7cf15caba..b4099a0aa 100644
--- a/lib/librte_eal/linux/eal_timer.c
+++ b/lib/librte_eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index c32007754..00752701f 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -330,6 +330,26 @@ EXPORTS
 	rte_thread_value_get
 	rte_thread_value_set
 
+	rte_thread_mutex_lock
+	rte_thread_mutex_unlock
+	rte_thread_mutex_init
+	rte_thread_mutex_destroy
+	rte_thread_create
+	rte_thread_set_affinity_by_id
+	rte_thread_get_affinity_by_id
+	rte_thread_set_priority
+	rte_thread_attr_init
+	rte_thread_attr_set_affinity
+	rte_thread_attr_get_affinity
+	rte_thread_attr_set_priority
+	rte_thread_join
+	rte_thread_self
+	rte_thread_equal
+	rte_thread_barrier_init
+	rte_thread_barrier_wait
+	rte_thread_barrier_destroy
+	rte_thread_cancel
+
 	rte_mem_lock
 	rte_mem_map
 	rte_mem_page_size
diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build
index 71221b84a..d3af6b6fe 100644
--- a/lib/librte_eal/unix/meson.build
+++ b/lib/librte_eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
 	'eal_file.c',
 	'eal_unix_memory.c',
 	'eal_unix_timer.c',
-	'rte_thread.c',
 )
diff --git a/lib/librte_eal/unix/rte_thread.c b/lib/librte_eal/unix/rte_thread.c
deleted file mode 100644
index c72d619ec..000000000
--- a/lib/librte_eal/unix/rte_thread.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_key_delete(rte_thread_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_value_set(rte_thread_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_value_get(rte_thread_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index e23745ae6..b562ee98d 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,6 +421,27 @@ EXPERIMENTAL {
 	rte_version_release;
 	rte_version_suffix;
 	rte_version_year;
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 2fc3d6141..faaf00972 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -368,6 +368,28 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -384,7 +406,9 @@ rte_eal_init(int argc, char **argv)
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
index 3b8266d38..9839a1fed 100644
--- a/lib/librte_eal/windows/eal_interrupts.c
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -7,7 +7,7 @@
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +76,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -94,7 +94,7 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 
 	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread(%lu)", intr_thread);
 		return -ENOENT;
 	}
 
diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c
index 9c3f6d69f..5ed495562 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -60,11 +60,11 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index dc5dc8240..4b92b198c 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/librte_eal/windows/include/meson.build b/lib/librte_eal/windows/include/meson.build
index b3534b025..7d9b3393e 100644
--- a/lib/librte_eal/windows/include/meson.build
+++ b/lib/librte_eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
deleted file mode 100644
index 9aeab1fa7..000000000
--- a/lib/librte_eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/librte_eal/windows/include/sched.h b/lib/librte_eal/windows/include/sched.h
index ff572b5dc..8f0b3cb71 100644
--- a/lib/librte_eal/windows/include/sched.h
+++ b/lib/librte_eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 42ff5c2d5..ffcddcd0c 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
 	'eal_timer.c',
 	'fnmatch.c',
 	'getopt.c',
-	'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'librte_eal/common/rte_thread.c'
+else
+	sources += 'librte_eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3059aa55b..72db655f6 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,7 +506,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -580,7 +580,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 918a34ed1..580108b95 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -5,7 +5,6 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
 #include <sys/types.h>
 
 /**
@@ -183,7 +182,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 241af6c4c..d096c3d57 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -223,14 +223,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index d8c635e99..33d8c7b54 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -121,7 +121,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1302,12 +1302,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 55d4856f9..b97774ccd 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index 3ab5cfdd6..ba58d849e 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 0169d3648..5f41d40ba 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,11 +1122,11 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 52ab93d1e..54db845da 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -646,7 +646,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -655,7 +655,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -663,12 +663,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 3b8c5d316..29f8df218 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -32,5 +32,7 @@ option('enable_trace_fp', type: 'boolean', value: false,
 	description: 'enable fast path trace points.')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false,
 	description: 'use HPET timer in EAL')
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-27 16:04             ` Stephen Hemminger
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  1 sibling, 0 replies; 290+ messages in thread
From: Stephen Hemminger @ 2021-03-27 16:04 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Fri, 26 Mar 2021 16:52:50 -0700
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Allow the user to choose the thread priority through an EAL
> command line argument.
> 
> The user can select the thread priority to be either 'normal'
> or 'critical':
> --thread-prio normal
> --thread-prio realtime
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>

Please don't add this. This will open up a huge set of bugs.
See the mailing list about how users report starvation and bug
checks on Windows when using real time.

In my experience, DPDK has same problem on Linux. The DPDK applications
(usually) poll at 100% CPU without system calls. If the user sets
these threads to real-time, then those threads have priority over kernel
background tasks (like handling soft interrupt or writing to the disk).
Therefore setting RT causes data loss or eventually RCU and watchdog
timeouts.

This patch encourages the fallacy that Real Time is faster.
The DPDK poll usage model is not compatible with the OS defintion
of real time. Real time is for processes doing system calls that
have precise timing requirements about when to wakeup from those
system calls.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading
  2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-03-27 16:04             ` Stephen Hemminger
@ 2021-03-29 22:40             ` Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                                 ` (9 more replies)
  1 sibling, 10 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application. If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  windows/eal: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +--
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |  36 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 +-
 lib/librte_eal/common/eal_common_thread.c     |  43 +-
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_internal_cfg.h      |   2 +
 lib/librte_eal/common/eal_options.h           |   2 +
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +-
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/common/rte_thread.c            | 342 ++++++++++++
 lib/librte_eal/freebsd/eal.c                  |  37 +-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/include/rte_thread.h           | 337 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/linux/eal.c                    |  42 +-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  20 +
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  92 ---
 lib/librte_eal/version.map                    |  21 +
 lib/librte_eal/windows/eal.c                  |  26 +-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_lcore.c            | 170 ++++--
 lib/librte_eal/windows/eal_thread.c           |  24 +-
 lib/librte_eal/windows/eal_windows.h          |  20 +-
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 -------
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_eal/windows/rte_thread.c           | 522 +++++++++++++++++-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 +-
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 +++--
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2038 insertions(+), 929 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 01/10] eal: add thread id and simple thread functions
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                 ` (8 subsequent siblings)
  9 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add the thread identifier type.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 101 ++++++++++++++++++
 lib/librte_eal/include/rte_thread.h           |  45 ++++++--
 lib/librte_eal/include/rte_thread_types.h     |  12 +++
 .../include/rte_windows_thread_types.h        |  12 +++
 lib/librte_eal/windows/rte_thread.c           |  13 +++
 5 files changed, 174 insertions(+), 9 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
new file mode 100644
index 000000000..5ec382949
--- /dev/null
+++ b/lib/librte_eal/common/rte_thread.c
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return pthread_self();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1, t2);
+}
+
+int
+rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_thread_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_key_delete(rte_thread_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_value_set(rte_thread_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_value_get(rte_thread_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 8be8ed8f3..cbc07f739 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_os.h>
@@ -20,6 +21,13 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -27,6 +35,31 @@ typedef struct eal_tls_key *rte_thread_key;
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
@@ -63,9 +96,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +111,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +126,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
new file mode 100644
index 000000000..19fb85e38
--- /dev/null
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+typedef pthread_t                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 000000000..ebd3d9e8f
--- /dev/null
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+typedef DWORD                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 667287c38..940d9c653 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,18 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1 == t2 ? 1 : 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 02/10] eal: add thread attributes
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-30 21:14                 ` Stephen Hemminger
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                 ` (7 subsequent siblings)
  9 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority

Implement functions for managing thread attributes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 53 ++++++++++++
 lib/librte_eal/include/rte_thread.h           | 82 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/librte_eal/windows/rte_thread.c           | 56 +++++++++++++
 5 files changed, 197 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 5ec382949..0bd1b115d 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,59 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index cbc07f739..bfdd8e1b1 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -28,6 +28,19 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,
+	/*
+	 * This enum can be extended to allow more priority levels.
+	 */
+};
+
+typedef struct {
+	enum rte_thread_priority priority;
+	rte_cpuset_t cpuset;
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -60,6 +73,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr;
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+				 enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 19fb85e38..a884daf17 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 typedef pthread_t                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index ebd3d9e8f..8cb4b3856 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 typedef DWORD                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 940d9c653..b29336cbd 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -24,6 +24,62 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to init thread attributes, invalid parameter\n");
+		return EINVAL;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-31 13:56                 ` Tal Shnaiderman
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                 ` (6 subsequent siblings)
  9 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/windows/rte_thread.c | 65 ++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 15 deletions(-)

diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index b29336cbd..e9181b47f 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -12,6 +12,47 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int rte_thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+
+	default:
+		return EINVAL;
+	}
+
+	return EINVAL;
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -87,15 +128,13 @@ rte_thread_key_create(rte_thread_key *key,
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
 		RTE_LOG_WIN32_ERR("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -103,16 +142,14 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
 		RTE_LOG_WIN32_ERR("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	free(key);
 	return 0;
@@ -123,17 +160,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
 		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error(GetLastError());
 	}
 	return 0;
 }
@@ -143,7 +178,7 @@ rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 04/10] eal: implement functions for thread affinity management
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (2 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                 ` (5 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c   |  13 ++
 lib/librte_eal/include/rte_thread.h  |  41 +++++++
 lib/librte_eal/windows/eal_lcore.c   | 170 +++++++++++++++++++--------
 lib/librte_eal/windows/eal_windows.h |  10 ++
 lib/librte_eal/windows/rte_thread.c  | 132 ++++++++++++++++++++-
 5 files changed, 318 insertions(+), 48 deletions(-)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 0bd1b115d..4f93e3ff1 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,19 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id, cpuset_size, cpuset);
+}
+
+int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index bfdd8e1b1..ed8330f81 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -73,6 +73,47 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset_size
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset_size
+ *    Size of the cpu set.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
index a85149be9..023c5c895 100644
--- a/lib/librte_eal/windows/eal_lcore.c
+++ b/lib/librte_eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -28,13 +27,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -48,13 +49,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -79,57 +178,27 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
-		}
+		if (eal_check_for_duplicate_numa(info))
+			break;
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -139,7 +208,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -165,3 +234,12 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	if (cpu_index < CPU_SETSIZE)
+		return &cpu_map.cpus[cpu_index];
+
+	return NULL;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index 478accc1b..dc5dc8240 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index e9181b47f..d60a3ded5 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -4,9 +4,9 @@
  */
 
 #include <rte_common.h>
-#include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -65,6 +65,134 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+			    size_t cpuset_size,
+			    const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 05/10] eal: implement thread priority management functions
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (3 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                 ` (4 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 25 ++++++++++
 lib/librte_eal/include/rte_thread.h | 17 +++++++
 lib/librte_eal/windows/rte_thread.c | 76 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 4f93e3ff1..26c5b1f3c 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -42,6 +42,31 @@ int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
 	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
 }
 
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int policy;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+
+
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+		policy = SCHED_RR;
+		param.sched_priority = priority;
+	} else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+		policy = SCHED_OTHER;
+		param.sched_priority = priority;
+	} else {
+		RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+				    "Defaulting to priority 'normal'.\n");
+		policy = SCHED_OTHER;
+	}
+
+	return pthread_setschedparam(thread_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index ed8330f81..34948dd90 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -114,6 +114,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 				  rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index d60a3ded5..544aaf33d 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -193,6 +193,82 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	DWORD priority_class = NORMAL_PRIORITY_CLASS;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	switch (priority) {
+
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		priority_class = REALTIME_PRIORITY_CLASS;
+		break;
+
+	case RTE_THREAD_PRIORITY_NORMAL:
+	/* FALLTHROUGH */
+	default:
+		priority_class = NORMAL_PRIORITY_CLASS;
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+		break;
+	}
+
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, priority)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 06/10] eal: add thread lifetime management
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (4 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                 ` (3 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 110 ++++++++++++++++++++++++
 lib/librte_eal/include/rte_thread.h |  53 ++++++++++++
 lib/librte_eal/windows/rte_thread.c | 125 ++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 26c5b1f3c..29d38d193 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -120,6 +120,116 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(thread_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 34948dd90..24dc186f1 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -200,6 +200,59 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 				 enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 544aaf33d..85b11c5f5 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -325,6 +325,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+
+	thread_handle = CreateThread(NULL, 0,
+				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,
+				args, 0, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("CreateThread()");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = rte_thread_translate_win32_error(GetLastError());
+				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = rte_thread_translate_win32_error(GetLastError());
+			RTE_LOG_WIN32_ERR("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 07/10] eal: implement functions for mutex management
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (5 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                 ` (2 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 24 +++++++++
 lib/librte_eal/include/rte_thread.h           | 53 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 ++
 .../include/rte_windows_thread_types.h        |  1 +
 lib/librte_eal/windows/rte_thread.c           | 28 ++++++++++
 5 files changed, 109 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 29d38d193..8e963ed65 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -220,6 +220,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 24dc186f1..2b8d81005 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -240,6 +240,58 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
@@ -259,6 +311,7 @@ int rte_thread_cancel(rte_thread_t thread_id);
  *
  * @param cpusetp
  *   Pointer to CPU affinity to set.
+ *
  * @return
  *   On success, return 0; otherwise return -1;
  */
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index a884daf17..37bc7af2b 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,9 +7,12 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
 #define EAL_THREAD_PRIORITY_NORMAL               0
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
 
 typedef pthread_t                       rte_thread_t;
+typedef pthread_mutex_t                 rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 8cb4b3856..47c6b2664 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -11,5 +11,6 @@
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
+typedef CRITICAL_SECTION            rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 85b11c5f5..a26b8c08f 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -417,6 +417,34 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 08/10] eal: implement functions for thread barrier management
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (6 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 16 +++++++
 lib/librte_eal/include/rte_thread.h           | 46 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  2 +
 .../include/rte_windows_thread_types.h        |  3 ++
 lib/librte_eal/windows/rte_thread.c           | 27 +++++++++++
 5 files changed, 94 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 8e963ed65..d23d3b868 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -244,6 +244,22 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	return pthread_barrier_init(barrier, NULL, count);
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_wait(barrier);
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_destroy(barrier);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 2b8d81005..5b4da8053 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -292,6 +292,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 37bc7af2b..b055bbf67 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
 #define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
 
 #define EAL_THREAD_PRIORITY_NORMAL               0
@@ -14,5 +15,6 @@
 
 typedef pthread_t                       rte_thread_t;
 typedef pthread_mutex_t                 rte_thread_mutex_t;
+typedef pthread_barrier_t               rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 47c6b2664..b6209e6eb 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,10 +7,13 @@
 
 #include <rte_windows.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
+
 #define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
 typedef CRITICAL_SECTION            rte_thread_mutex_t;
+typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index a26b8c08f..c3c198663 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -445,6 +445,33 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+
+	if (!InitializeSynchronizationBarrier(barrier, count, -1)) {
+		ret = rte_thread_translate_win32_error(GetLastError());
+		RTE_LOG_WIN32_ERR("InitializeSynchronizationBarrier()");
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return EnterSynchronizationBarrier(barrier,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	DeleteSynchronizationBarrier(barrier);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (7 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  2021-03-30 21:11                 ` Stephen Hemminger
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  9 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can select the thread priority to be either 'normal'
or 'critical':
--thread-prio normal
--thread-prio realtime

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/eal_common_options.c | 28 +++++++++++++++++++++-
 lib/librte_eal/common/eal_internal_cfg.h   |  2 ++
 lib/librte_eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 622c7bc42..287a89a75 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -106,6 +106,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1383,6 +1384,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1796,7 +1815,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2059,6 +2084,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 51dbe86e2..7ab1d0008 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -93,6 +93,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 7b348e707..9f5b209f6 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v5 10/10] Enable the new EAL thread API
  2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                 ` (8 preceding siblings ...)
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-29 22:40               ` Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-03-29 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +--
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 ++--
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +++----
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |   8 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 ++---
 lib/librte_eal/common/eal_common_thread.c     |  43 ++--
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +--
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/freebsd/eal.c                  |  37 +++-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/linux/eal.c                    |  42 +++-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  20 ++
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  92 ---------
 lib/librte_eal/version.map                    |  21 ++
 lib/librte_eal/windows/eal.c                  |  26 ++-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_thread.c           |  24 +--
 lib/librte_eal/windows/eal_windows.h          |  10 -
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------------------
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 ++--
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++++++------
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 659 insertions(+), 856 deletions(-)
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index 27f1b1c0e..ff284335a 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 #endif
 #endif
 
@@ -127,7 +127,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
-		pthread_create(&thread, NULL, &send_pkts, NULL);
+		rte_thread_create(&thread, NULL, &send_pkts, NULL);
 #endif
 #endif
 
@@ -137,7 +137,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fc..c507e423e 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a..3d9663f5e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d06..ce79d9c17 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 66a2edcc4..8db5bd725 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -258,6 +258,10 @@ else # for 32-bit we need smaller reserved memory areas
 	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da..a9e6013ff 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,11 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a..dc5f02bec 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681c..6d2d10cdf 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1..c826ad0c1 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -92,10 +92,10 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index ec3c23751..d2bda960f 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -73,7 +73,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -833,9 +833,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -855,13 +855,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb/pf/base/dlb_osdep.h b/drivers/event/dlb/pf/base/dlb_osdep.h
index dee20660e..cc22b85d6 100644
--- a/drivers/event/dlb/pf/base/dlb_osdep.h
+++ b/drivers/event/dlb/pf/base/dlb_osdep.h
@@ -208,7 +208,7 @@ static void *dlb_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb_hw *hw)
 {
 	struct dlb_dev *dlb_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb_dev = container_of(hw, struct dlb_dev, hw);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index aa101a49a..b002dc774 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index a64fef1cf..355f98534 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -179,7 +179,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -670,7 +670,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -681,7 +681,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -719,7 +719,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -745,7 +745,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -774,9 +774,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -942,9 +942,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index ef650a465..89d6b2bb4 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -618,12 +618,12 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
 		 */
-		if (pthread_create(&thread, NULL, delay_pg_start, ark)) {
+		if (rte_thread_create(&thread, NULL, delay_pg_start, ark)) {
 			ARK_PMD_LOG(ERR, "Could not create pktgen "
 				    "starter thread\n");
 			return -1;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f..96b7da3ac 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f32..93e41aa26 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405..a6f576dab 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b..197c72290 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876..e6f252e09 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729f..cfd436fa6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12..c17f9a8b9 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695a..5f3d9b360 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec19..1e1d6358d 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index de1b4af91..ef9be3847 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -533,8 +533,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -693,7 +693,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -747,18 +747,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -944,10 +944,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3..a50511047 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index f1dd40591..340608b60 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1043,7 +1043,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1053,20 +1053,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1443,14 +1443,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1532,13 +1532,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1571,14 +1571,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4066,7 +4066,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4074,7 +4074,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4244,7 +4244,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4259,7 +4259,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5048,25 +5048,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5833,14 +5833,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d..e1d980cf9 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index d94874578..472e6fead 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef9..455d83bef 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061..88d64d703 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd683..26c3e7551 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea..cb6bbcad6 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83..f06bd2b27 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2..1115afa81 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 932600d05..d8305f9ea 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -433,7 +433,7 @@ struct hns3_hw {
 	struct hns3_cmq cmq;
 	struct hns3_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hns3_mbx_arq_ring arq;         /* mailbox async rx queue */
-	pthread_t irq_thread_id;
+	rte_thread_t irq_thread_id;
 	struct hns3_mac mac;
 	unsigned int secondary_cnt; /* Number of secondary processes init'd. */
 	struct hns3_tqp_stats tqp_stats;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index fd20c522d..d78b45866 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1107,7 +1107,7 @@ hns3vf_interrupt_handler(void *param)
 	uint32_t clearval;
 
 	if (hw->irq_thread_id == 0)
-		hw->irq_thread_id = pthread_self();
+		hw->irq_thread_id = rte_thread_self();
 
 	/* Disable interrupt */
 	hns3vf_disable_irq0(hw);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 61d15845e..34d2458b1 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -101,7 +101,7 @@ hns3_get_mbx_resp(struct hns3_hw *hw, uint16_t code0, uint16_t code1,
 		 * Sending mbox in the interrupt thread cannot wait for the
 		 * response, so polling the mbox response on the irq thread.
 		 */
-		if (pthread_equal(hw->irq_thread_id, pthread_self())) {
+		if (rte_thread_equal(hw->irq_thread_id, rte_thread_self())) {
 			in_irq = true;
 			hns3_poll_all_sync_msg();
 		} else {
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 476fd4906..66bc7d683 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -152,7 +152,7 @@ static void
 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 {
 	struct ice_dcf_reset_event_param *param;
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
@@ -165,7 +165,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 	param->vfr = vfr;
 	param->vf_id = vf_id;
 
-	ret = pthread_create(&thread, NULL,
+	ret = rte_thread_create(&thread, NULL,
 			     ice_dcf_vsi_update_service_handler, param);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling");
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 856d21ef9..aa55e6fc0 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 8a9a21e7c..fcd80fbb6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4148,7 +4148,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	pthread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca2..272fdcfb8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549..3518b913e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 5e3ae9f10..21689c596 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2349,7 +2349,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index abd7ff70d..57645aed1 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -181,7 +181,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -884,7 +884,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1010,11 +1010,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1046,7 +1046,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1077,7 +1077,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1108,11 +1108,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2234,7 +2234,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 14043b68d..40e5bc76c 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -632,7 +632,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index e8d632ad2..2a149f5bf 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -904,7 +904,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -920,7 +920,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -947,7 +947,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -955,7 +955,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index c4d579072..229bad3ea 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_thread_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 6f3927614..956e92d68 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -226,7 +226,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b539928..f0cb71c93 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8..1004ec289 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 1b54d55bd..2052d03a3 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -142,7 +142,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -160,7 +160,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -184,7 +184,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -205,12 +205,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -225,7 +225,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -248,11 +248,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -379,7 +379,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -404,7 +404,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -490,7 +490,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -795,13 +795,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -811,7 +811,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -836,7 +836,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 8a62f7ea7..db393e55b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -56,7 +56,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 05d79bfcc..6f97695e0 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -526,7 +526,7 @@ ifpga_monitor_start_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 0) {
-		ret = pthread_create(&ifpga_monitor_start_thread,
+		ret = rte_thread_create(&ifpga_monitor_start_thread,
 			NULL,
 			ifpga_rawdev_gsd_handle, NULL);
 		if (ret) {
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 39237aecf..6ff8dd123 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -50,7 +50,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -77,7 +77,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -87,7 +87,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -96,7 +96,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -110,7 +110,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -120,7 +120,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -496,7 +496,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, notify_relay,
+	ret = rte_thread_create(&internal->tid, NULL, notify_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create notify relay pthread.");
@@ -508,11 +508,9 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -799,7 +797,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, vring_relay,
+	ret = rte_thread_create(&internal->tid, NULL, vring_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create ring relay pthread.");
@@ -811,11 +809,9 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -1245,9 +1241,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1285,9 +1281,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 898e50f80..bcb744f5b 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -764,10 +764,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -798,7 +798,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -807,7 +807,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -816,7 +816,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index d93b430c9..568b84c3f 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 404e135d5..ebb53f4b1 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -247,17 +247,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -281,13 +281,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -297,7 +297,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -313,7 +313,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -332,7 +332,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -347,13 +347,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -369,7 +369,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -415,7 +415,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -502,47 +502,39 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+		rte_thread_attr_init(&attr);
+		CPU_ZERO(&cpuset);
+		if (priv->event_core != -1)
+			CPU_SET(priv->event_core, &cpuset);
+		else
+			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr,
+					RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
 			return -1;
 		}
-		CPU_ZERO(&cpuset);
-		if (priv->event_core != -1)
-			CPU_SET(priv->event_core, &cpuset);
-		else
-			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_setaffinity_np(priv->timer_tid,
-					     sizeof(cpuset), &cpuset);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread affinity.");
-			goto error;
-		}
 		snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
 		ret = pthread_setname_np(priv->timer_tid, name);
 		if (ret) {
@@ -569,7 +561,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -586,8 +577,8 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
 	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
 	priv->timer_tid = 0;
 }
diff --git a/examples/kni/main.c b/examples/kni/main.c
index fe93b8618..d29cbf7ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 2ca7d98c5..c3b2273ef 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1635,7 +1635,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index 7ea60863d..5ea1b45ac 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, sizeof(cpu_set_t), &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring;
 
@@ -672,7 +672,7 @@ new_device(int vid)
 	/* start polling vring */
 	worker_thread_status = WORKER_STATE_START;
 	fprintf(stdout, "New Device %s, Device ID %d\n", path, vid);
-	if (pthread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
+	if (rte_thread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
 		fprintf(stderr, "Worker Thread Started Failed\n");
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 287a89a75..839d837f2 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -1843,8 +1843,8 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t),  &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1872,8 +1872,8 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					  sizeof(rte_cpuset_t), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
index 6d1af3c0e..6eb2bbb3a 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 73a055902..4cd09d230 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,9 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,7 +168,7 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 };
 
 static void *ctrl_thread_init(void *arg)
@@ -184,9 +183,9 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
@@ -194,8 +193,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -211,9 +210,9 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->start_routine = start_routine;
 	params->arg = arg;
 
-	pthread_barrier_init(&params->configured, NULL, 2);
+	rte_thread_barrier_init(&params->configured, 2);
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, params);
 	if (ret != 0) {
 		free(params);
 		return -ret;
@@ -226,26 +225,26 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, sizeof(*cpuset), cpuset);
 	if (ret)
 		goto fail;
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
 	return 0;
 
 fail:
-	if (PTHREAD_BARRIER_SERIAL_THREAD ==
-	    pthread_barrier_wait(&params->configured)) {
-		pthread_barrier_destroy(&params->configured);
+	if (RTE_THREAD_BARRIER_SERIAL_THREAD ==
+	    rte_thread_barrier_wait(&params->configured)) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
-	pthread_cancel(*thread);
-	pthread_join(*thread, NULL);
+	rte_thread_cancel(*thread);
+	rte_thread_join(*thread, NULL);
 	return -ret;
 }
 
@@ -266,7 +265,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), sizeof(cpuset),
 			&cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 24e27387b..6df4a0127 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b8a0d2002..d5a6abe9a 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index c7101b32d..fdc3a2cfe 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 70bd854fe..4cd4e8e70 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
 	'rte_random.c',
 	'rte_reciprocal.c',
 	'rte_service.c',
+	'rte_thread.c',
 	'rte_version.c',
 )
 
diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c
index 32442e5ba..0960dc90e 100644
--- a/lib/librte_eal/freebsd/eal.c
+++ b/lib/librte_eal/freebsd/eal.c
@@ -663,7 +663,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -686,7 +686,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -850,7 +850,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,6 +873,21 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -878,8 +901,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -889,10 +914,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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_alarm.c b/lib/librte_eal/freebsd/eal_alarm.c
index c38b2e04f..e5d7b130b 100644
--- a/lib/librte_eal/freebsd/eal_alarm.c
+++ b/lib/librte_eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/freebsd/eal_interrupts.c b/lib/librte_eal/freebsd/eal_interrupts.c
index 72eeacbc1..de5d2b733 100644
--- a/lib/librte_eal/freebsd/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -725,5 +725,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c
index 1dce9b04f..082a66917 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 3969cf4ac..0b6feb377 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
 	'rte_string_fns.h',
 	'rte_tailq.h',
 	'rte_thread.h',
+	'rte_thread_types.h',
 	'rte_time.h',
 	'rte_trace.h',
 	'rte_trace_point.h',
diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h
index 1550b75da..d5e004105 100644
--- a/lib/librte_eal/include/rte_lcore.h
+++ b/lib/librte_eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/librte_eal/include/rte_per_lcore.h b/lib/librte_eal/include/rte_per_lcore.h
index eaedf0cb3..025d97f96 100644
--- a/lib/librte_eal/include/rte_per_lcore.h
+++ b/lib/librte_eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c
index abbb53774..76f2daa26 100644
--- a/lib/librte_eal/linux/eal.c
+++ b/lib/librte_eal/linux/eal.c
@@ -958,7 +958,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -986,7 +986,7 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1214,7 +1214,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1228,6 +1236,23 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, (uintptr_t)thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1241,9 +1266,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1255,11 +1282,6 @@ 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_alarm.c b/lib/librte_eal/linux/eal_alarm.c
index 3252c6fa5..fef22a347 100644
--- a/lib/librte_eal/linux/eal_alarm.c
+++ b/lib/librte_eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/linux/eal_interrupts.c b/lib/librte_eal/linux/eal_interrupts.c
index 1dd994bd1..bc38055b8 100644
--- a/lib/librte_eal/linux/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1558,5 +1558,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c
index 83c2034b9..bd447d6a2 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -164,7 +164,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/lib/librte_eal/linux/eal_timer.c b/lib/librte_eal/linux/eal_timer.c
index 7cf15caba..b4099a0aa 100644
--- a/lib/librte_eal/linux/eal_timer.c
+++ b/lib/librte_eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index c32007754..00752701f 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -330,6 +330,26 @@ EXPORTS
 	rte_thread_value_get
 	rte_thread_value_set
 
+	rte_thread_mutex_lock
+	rte_thread_mutex_unlock
+	rte_thread_mutex_init
+	rte_thread_mutex_destroy
+	rte_thread_create
+	rte_thread_set_affinity_by_id
+	rte_thread_get_affinity_by_id
+	rte_thread_set_priority
+	rte_thread_attr_init
+	rte_thread_attr_set_affinity
+	rte_thread_attr_get_affinity
+	rte_thread_attr_set_priority
+	rte_thread_join
+	rte_thread_self
+	rte_thread_equal
+	rte_thread_barrier_init
+	rte_thread_barrier_wait
+	rte_thread_barrier_destroy
+	rte_thread_cancel
+
 	rte_mem_lock
 	rte_mem_map
 	rte_mem_page_size
diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build
index 71221b84a..d3af6b6fe 100644
--- a/lib/librte_eal/unix/meson.build
+++ b/lib/librte_eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
 	'eal_file.c',
 	'eal_unix_memory.c',
 	'eal_unix_timer.c',
-	'rte_thread.c',
 )
diff --git a/lib/librte_eal/unix/rte_thread.c b/lib/librte_eal/unix/rte_thread.c
deleted file mode 100644
index c72d619ec..000000000
--- a/lib/librte_eal/unix/rte_thread.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_key_delete(rte_thread_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_value_set(rte_thread_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_value_get(rte_thread_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index e23745ae6..b562ee98d 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,6 +421,27 @@ EXPERIMENTAL {
 	rte_version_release;
 	rte_version_suffix;
 	rte_version_year;
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 2fc3d6141..faaf00972 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -368,6 +368,28 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -384,7 +406,9 @@ rte_eal_init(int argc, char **argv)
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
index 3b8266d38..9839a1fed 100644
--- a/lib/librte_eal/windows/eal_interrupts.c
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -7,7 +7,7 @@
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +76,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -94,7 +94,7 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 
 	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread(%lu)", intr_thread);
 		return -ENOENT;
 	}
 
diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c
index 9c3f6d69f..5ed495562 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -60,11 +60,11 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index dc5dc8240..4b92b198c 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/librte_eal/windows/include/meson.build b/lib/librte_eal/windows/include/meson.build
index b3534b025..7d9b3393e 100644
--- a/lib/librte_eal/windows/include/meson.build
+++ b/lib/librte_eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
deleted file mode 100644
index 9aeab1fa7..000000000
--- a/lib/librte_eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/librte_eal/windows/include/sched.h b/lib/librte_eal/windows/include/sched.h
index ff572b5dc..8f0b3cb71 100644
--- a/lib/librte_eal/windows/include/sched.h
+++ b/lib/librte_eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 42ff5c2d5..ffcddcd0c 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
 	'eal_timer.c',
 	'fnmatch.c',
 	'getopt.c',
-	'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'librte_eal/common/rte_thread.c'
+else
+	sources += 'librte_eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3059aa55b..72db655f6 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,7 +506,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -580,7 +580,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 918a34ed1..580108b95 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -5,7 +5,6 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
 #include <sys/types.h>
 
 /**
@@ -183,7 +182,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 241af6c4c..d096c3d57 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -223,14 +223,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index d8c635e99..33d8c7b54 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -121,7 +121,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1302,12 +1302,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 55d4856f9..b97774ccd 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index 3ab5cfdd6..ba58d849e 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 0169d3648..5f41d40ba 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,11 +1122,11 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 52ab93d1e..54db845da 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -646,7 +646,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -655,7 +655,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -663,12 +663,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 3b8c5d316..29f8df218 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -32,5 +32,7 @@ option('enable_trace_fp', type: 'boolean', value: false,
 	description: 'enable fast path trace points.')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false,
 	description: 'use HPET timer in EAL')
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-03-30 21:11                 ` Stephen Hemminger
  2021-03-31  8:21                   ` Tal Shnaiderman
  2021-03-31 21:12                   ` Dmitry Kozlyuk
  0 siblings, 2 replies; 290+ messages in thread
From: Stephen Hemminger @ 2021-03-30 21:11 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Mon, 29 Mar 2021 15:40:39 -0700
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Allow the user to choose the thread priority through an EAL
> command line argument.
> 
> The user can select the thread priority to be either 'normal'
> or 'critical':
> --thread-prio normal
> --thread-prio realtime
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>

The discussion internally was that this was intended to resolve issues on Windows.
So it makes sense for Windows, but it is not something that we want to have on Linux.
Could you make this Windows only, and add update the documentation please.

I just don't want Linux users discovering it, trying it, then reporting more bugs.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 02/10] eal: add thread attributes
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-03-30 21:14                 ` Stephen Hemminger
  0 siblings, 0 replies; 290+ messages in thread
From: Stephen Hemminger @ 2021-03-30 21:14 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Mon, 29 Mar 2021 15:40:32 -0700
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> +
> +int
> +rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
> +			     enum rte_thread_priority priority)
> +{
> +	if (thread_attr == NULL) {
> +		RTE_LOG(DEBUG, EAL,
> +			"Unable to set priority attribute, invalid parameter\n");
> +		return EINVAL;
> +	}
> +
> +	thread_attr->priority = priority;
> +	return 0;
> +}

For Linux, shouldn't this be ENOTSUPP since not supported.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority
  2021-03-30 21:11                 ` Stephen Hemminger
@ 2021-03-31  8:21                   ` Tal Shnaiderman
  2021-03-31 21:12                   ` Dmitry Kozlyuk
  1 sibling, 0 replies; 290+ messages in thread
From: Tal Shnaiderman @ 2021-03-31  8:21 UTC (permalink / raw)
  To: Stephen Hemminger, Narcisa Ana Maria Vasile
  Cc: dev, NBU-Contact-Thomas Monjalon, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

> Subject: Re: [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting
> thread priority
> 
> External email: Use caution opening links or attachments
> 
> 
> On Mon, 29 Mar 2021 15:40:39 -0700
> Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:
> 
> > From: Narcisa Vasile <navasile@microsoft.com>
> >
> > Allow the user to choose the thread priority through an EAL command
> > line argument.
> >
> > The user can select the thread priority to be either 'normal'
> > or 'critical':
> > --thread-prio normal
> > --thread-prio realtime
> >
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> 
> The discussion internally was that this was intended to resolve issues on
> Windows.
> So it makes sense for Windows, but it is not something that we want to have
> on Linux.
> Could you make this Windows only, and add update the documentation
> please.
> 
> I just don't want Linux users discovering it, trying it, then reporting more
> bugs.

Windows needs it from performance aspects.

However if we're keeping this option for Windows a warning like the one below from MSDN [1] should be added to docu:

" A thread with a base priority level above 11 interferes with the normal operation of the operating system. Using REALTIME_PRIORITY_CLASS may cause disk caches to not flush, cause the mouse to stop responding, and so on. "

[1] - https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-03-31 13:56                 ` Tal Shnaiderman
  2021-03-31 21:19                   ` Nick Connolly
  2021-04-01 19:07                   ` Narcisa Ana Maria Vasile
  0 siblings, 2 replies; 290+ messages in thread
From: Tal Shnaiderman @ 2021-03-31 13:56 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile, dev, NBU-Contact-Thomas Monjalon,
	dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

> Subject: [PATCH v5 03/10] windows/eal: translate Windows errors to errno-
> style errors
> 
> External email: Use caution opening links or attachments
> 
> 
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add function to translate Windows error codes to errno-style error codes.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/librte_eal/windows/rte_thread.c | 65 ++++++++++++++++++++++-------
>  1 file changed, 50 insertions(+), 15 deletions(-)
> 
> diff --git a/lib/librte_eal/windows/rte_thread.c
> b/lib/librte_eal/windows/rte_thread.c
> index b29336cbd..e9181b47f 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -12,6 +12,47 @@ struct eal_tls_key {
>         DWORD thread_index;
>  };
> 
> +/* Translates the most common error codes related to threads */ static
> +int rte_thread_translate_win32_error(DWORD error) {

This DWORD error will always the output of GetLastError()? If so can we move it inside the function?

Also, I don't think this is a thread specific function, other implementations can use it in the future, maybe move it to rte_windows.h? 

> +       switch (error) {
> +       case ERROR_SUCCESS:
> +               return 0;
> +
> +       case ERROR_INVALID_PARAMETER:
> +               return EINVAL;
> +
> +       case ERROR_INVALID_HANDLE:
> +               return EFAULT;
> +
> +       case ERROR_NOT_ENOUGH_MEMORY:
> +       /* FALLTHROUGH */
> +       case ERROR_NO_SYSTEM_RESOURCES:
> +               return ENOMEM;
> +
> +       case ERROR_PRIVILEGE_NOT_HELD:
> +       /* FALLTHROUGH */
> +       case ERROR_ACCESS_DENIED:
> +               return EACCES;
> +
> +       case ERROR_ALREADY_EXISTS:
> +               return EEXIST;
> +
> +       case ERROR_POSSIBLE_DEADLOCK:
> +               return EDEADLK;
> +
> +       case ERROR_INVALID_FUNCTION:
> +       /* FALLTHROUGH */
> +       case ERROR_CALL_NOT_IMPLEMENTED:
> +               return ENOSYS;
> +
> +       default:
> +               return EINVAL;
> +       }
> +
> +       return EINVAL;
> +}
> +
>  rte_thread_t
>  rte_thread_self(void)
>  {
> @@ -87,15 +128,13 @@ rte_thread_key_create(rte_thread_key *key,
>         *key = malloc(sizeof(**key));
>         if ((*key) == NULL) {
>                 RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
> -               rte_errno = ENOMEM;
> -               return -1;
> +               return ENOMEM;
>         }
>         (*key)->thread_index = TlsAlloc();
>         if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
>                 RTE_LOG_WIN32_ERR("TlsAlloc()");
>                 free(*key);
> -               rte_errno = ENOEXEC;
> -               return -1;
> +               return rte_thread_translate_win32_error(GetLastError());
>         }
>         return 0;
>  }
> @@ -103,16 +142,14 @@ rte_thread_key_create(rte_thread_key *key,  int
> rte_thread_key_delete(rte_thread_key key)  {
> -       if (!key) {
> +       if (key == NULL) {
>                 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
> -               rte_errno = EINVAL;
> -               return -1;
> +               return EINVAL;
>         }
>         if (!TlsFree(key->thread_index)) {
>                 RTE_LOG_WIN32_ERR("TlsFree()");
>                 free(key);
> -               rte_errno = ENOEXEC;
> -               return -1;
> +               return rte_thread_translate_win32_error(GetLastError());
>         }
>         free(key);
>         return 0;
> @@ -123,17 +160,15 @@ rte_thread_value_set(rte_thread_key key, const
> void *value)  {
>         char *p;
> 
> -       if (!key) {
> +       if (key == NULL) {
>                 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
> -               rte_errno = EINVAL;
> -               return -1;
> +               return EINVAL;
>         }
>         /* discard const qualifier */
>         p = (char *) (uintptr_t) value;
>         if (!TlsSetValue(key->thread_index, p)) {
>                 RTE_LOG_WIN32_ERR("TlsSetValue()");
> -               rte_errno = ENOEXEC;
> -               return -1;
> +               return rte_thread_translate_win32_error(GetLastError());
>         }
>         return 0;
>  }
> @@ -143,7 +178,7 @@ rte_thread_value_get(rte_thread_key key)  {
>         void *output;
> 

This function is missing the change to rte_thread_translate_win32_error.
Aldo need to change function docu.

> -       if (!key) {
> +       if (key == NULL) {
>                 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
>                 rte_errno = EINVAL;
>                 return NULL;
> --
> 2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority
  2021-03-30 21:11                 ` Stephen Hemminger
  2021-03-31  8:21                   ` Tal Shnaiderman
@ 2021-03-31 21:12                   ` Dmitry Kozlyuk
  2021-03-31 22:09                     ` Stephen Hemminger
  1 sibling, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-31 21:12 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Narcisa Ana Maria Vasile, dev, thomas, khot, navasile, dmitrym,
	roretzla, talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

2021-03-30 14:11 (UTC-0700), Stephen Hemminger:
> On Mon, 29 Mar 2021 15:40:39 -0700
> Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:
> 
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Allow the user to choose the thread priority through an EAL
> > command line argument.
> > 
> > The user can select the thread priority to be either 'normal'
> > or 'critical':
> > --thread-prio normal
> > --thread-prio realtime
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>  
> 
> The discussion internally was that this was intended to resolve issues on Windows.
> So it makes sense for Windows, but it is not something that we want to have on Linux.
> Could you make this Windows only, and add update the documentation please.
> 
> I just don't want Linux users discovering it, trying it, then reporting more bugs.

Can you share more details of that discussion?
Is realtime-critical needed not for busy-polling apps (which indeed cause
starvation), but for interrupt-driven ones to process packets ASAP?

If it's true, then maybe NetUIO can instead give priority boost to these
threads when notifying them about interrupts (Omar? DmitryM?). This can be
configurable via devargs. One downside is that every kernel driver has to
support it, currently Mellanox bifurcated driver and NetUIO. But they will
need some interrupt-related IOCTLs anyway.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-31 13:56                 ` Tal Shnaiderman
@ 2021-03-31 21:19                   ` Nick Connolly
  2021-04-01 12:29                     ` Tal Shnaiderman
  2021-04-01 19:07                   ` Narcisa Ana Maria Vasile
  1 sibling, 1 reply; 290+ messages in thread
From: Nick Connolly @ 2021-03-31 21:19 UTC (permalink / raw)
  To: Tal Shnaiderman, Narcisa Ana Maria Vasile, dev,
	NBU-Contact-Thomas Monjalon, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam


> Also, I don't think this is a thread specific function, other implementations can use it in the future, maybe move it to rte_windows.h?

I'd suggest that it's probably better suited to a .c file rather
than a header.  As an example of what it might end up like
see https://github.com/wpdk/wpdk/blob/master/src/error.c

Regards,
Nick



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority
  2021-03-31 21:12                   ` Dmitry Kozlyuk
@ 2021-03-31 22:09                     ` Stephen Hemminger
  2021-03-31 22:42                       ` [dpdk-dev] [EXTERNAL] " Dmitry Malloy
  0 siblings, 1 reply; 290+ messages in thread
From: Stephen Hemminger @ 2021-03-31 22:09 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Narcisa Ana Maria Vasile, dev, thomas, khot, navasile, dmitrym,
	roretzla, talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Thu, 1 Apr 2021 00:12:54 +0300
Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:

> 2021-03-30 14:11 (UTC-0700), Stephen Hemminger:
> > On Mon, 29 Mar 2021 15:40:39 -0700
> > Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:
> >   
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > > 
> > > Allow the user to choose the thread priority through an EAL
> > > command line argument.
> > > 
> > > The user can select the thread priority to be either 'normal'
> > > or 'critical':
> > > --thread-prio normal
> > > --thread-prio realtime
> > > 
> > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>    
> > 
> > The discussion internally was that this was intended to resolve issues on Windows.
> > So it makes sense for Windows, but it is not something that we want to have on Linux.
> > Could you make this Windows only, and add update the documentation please.
> > 
> > I just don't want Linux users discovering it, trying it, then reporting more bugs.  
> 
> Can you share more details of that discussion?
> Is realtime-critical needed not for busy-polling apps (which indeed cause
> starvation), but for interrupt-driven ones to process packets ASAP?
> 
> If it's true, then maybe NetUIO can instead give priority boost to these
> threads when notifying them about interrupts (Omar? DmitryM?). This can be
> configurable via devargs. One downside is that every kernel driver has to
> support it, currently Mellanox bifurcated driver and NetUIO. But they will
> need some interrupt-related IOCTLs anyway.


A DPDK application typically has cores detected to polling for packets.
The temptation is to set those cores to have a real time scheduling policy
(SCHED_FIFO, or SCH_RR).  The problem is that those priorities run in preference
to required kernel functions. So the polling-for-packets threads will starve
out the Linux kernel RCU and softirq completion of I/O.  This starvation
will lead to memory loss (no RCU cleanup) and potential deadlocks (disk
I/O never completing).

It is possible to use real time priority on Linux but it requires lots of tuning
to make sure that the kernel never runs work queues, interrupts or soft irqs
on those cores. Lots of changes to /proc, kernel command line, and sysfs
tunables. Which is possible on embedded systems but not for general purpose
applications.

This is already a problem that shows up, but it only happens if the DPDK
application writer explcitly calls the setscheduler on those threads.
At that point, it is the case where the user has started to manipulate
threads, and we have to assume they know the consequences and are ready
to deal with them.

On Windows, the situation is different so yes, this is necessary.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v5 09/10] eal: add EAL argument for setting thread priority
  2021-03-31 22:09                     ` Stephen Hemminger
@ 2021-03-31 22:42                       ` Dmitry Malloy
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Malloy @ 2021-03-31 22:42 UTC (permalink / raw)
  To: Stephen Hemminger, Dmitry Kozlyuk
  Cc: Narcisa Ana Maria Vasile, dev, thomas, Khoa To,
	Narcisa Ana Maria Vasile, Tyler Retzlaff, talshn, Omar Cardona,
	bruce.richardson, david.marchand, Kadam, Pallavi

The internal discussion was about the fact that this EAL parameter is:

a) optional
b) modifies default behavior (which is different on Windows or on Linux)

Unless admin decides to use this option - no one is regressed. This patch is not forcing a change in default behavior. It gives the admin a choice to change the priority. From this perspective - is see no problem with it.

Thanks,
Dmitry

-----Original Message-----
From: Stephen Hemminger <stephen@networkplumber.org> 
Sent: Wednesday, March 31, 2021 3:09 PM
To: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Cc: Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>; dev@dpdk.org; thomas <thomas@monjalon.net>; Khoa To <khot@microsoft.com>; Narcisa Ana Maria Vasile <Narcisa.Vasile@microsoft.com>; Dmitry Malloy <dmitrym@microsoft.com>; Tyler Retzlaff <roretzla@microsoft.com>; talshn@nvidia.com; Omar Cardona <ocardona@microsoft.com>; bruce.richardson@intel.com; david.marchand@redhat.com; Kadam, Pallavi <pallavi.kadam@intel.com>
Subject: [EXTERNAL] Re: [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority

On Thu, 1 Apr 2021 00:12:54 +0300
Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:

> 2021-03-30 14:11 (UTC-0700), Stephen Hemminger:
> > On Mon, 29 Mar 2021 15:40:39 -0700
> > Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:
> >   
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > > 
> > > Allow the user to choose the thread priority through an EAL 
> > > command line argument.
> > > 
> > > The user can select the thread priority to be either 'normal'
> > > or 'critical':
> > > --thread-prio normal
> > > --thread-prio realtime
> > > 
> > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>    
> > 
> > The discussion internally was that this was intended to resolve issues on Windows.
> > So it makes sense for Windows, but it is not something that we want to have on Linux.
> > Could you make this Windows only, and add update the documentation please.
> > 
> > I just don't want Linux users discovering it, trying it, then reporting more bugs.  
> 
> Can you share more details of that discussion?
> Is realtime-critical needed not for busy-polling apps (which indeed 
> cause starvation), but for interrupt-driven ones to process packets ASAP?
> 
> If it's true, then maybe NetUIO can instead give priority boost to 
> these threads when notifying them about interrupts (Omar? DmitryM?). 
> This can be configurable via devargs. One downside is that every 
> kernel driver has to support it, currently Mellanox bifurcated driver 
> and NetUIO. But they will need some interrupt-related IOCTLs anyway.


A DPDK application typically has cores detected to polling for packets.
The temptation is to set those cores to have a real time scheduling policy (SCHED_FIFO, or SCH_RR).  The problem is that those priorities run in preference to required kernel functions. So the polling-for-packets threads will starve out the Linux kernel RCU and softirq completion of I/O.  This starvation will lead to memory loss (no RCU cleanup) and potential deadlocks (disk I/O never completing).

It is possible to use real time priority on Linux but it requires lots of tuning to make sure that the kernel never runs work queues, interrupts or soft irqs on those cores. Lots of changes to /proc, kernel command line, and sysfs tunables. Which is possible on embedded systems but not for general purpose applications.

This is already a problem that shows up, but it only happens if the DPDK application writer explcitly calls the setscheduler on those threads.
At that point, it is the case where the user has started to manipulate threads, and we have to assume they know the consequences and are ready to deal with them.

On Windows, the situation is different so yes, this is necessary.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-31 21:19                   ` Nick Connolly
@ 2021-04-01 12:29                     ` Tal Shnaiderman
  0 siblings, 0 replies; 290+ messages in thread
From: Tal Shnaiderman @ 2021-04-01 12:29 UTC (permalink / raw)
  To: Nick Connolly, Narcisa Ana Maria Vasile, dev,
	NBU-Contact-Thomas Monjalon, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

> Subject: Re: [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows
> errors to errno-style errors
> 
> External email: Use caution opening links or attachments
> 
> 
> > Also, I don't think this is a thread specific function, other implementations
> can use it in the future, maybe move it to rte_windows.h?
> 
> I'd suggest that it's probably better suited to a .c file rather than a header.  As
> an example of what it might end up like see
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgith
> ub.com%2Fwpdk%2Fwpdk%2Fblob%2Fmaster%2Fsrc%2Ferror.c&amp;data=
> 04%7C01%7Ctalshn%40nvidia.com%7C4ab2e17b824842b9f83208d8f48ab4ec
> %7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C637528223860057761
> %7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiL
> CJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=AnBHMtSobODNzb
> Uhun3GVnsTiePl%2BQzfPSASlur81Ks%3D&amp;reserved=0
> 
> Regards,
> Nick
> 

Agreed, thanks Nick.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-03-31 13:56                 ` Tal Shnaiderman
  2021-03-31 21:19                   ` Nick Connolly
@ 2021-04-01 19:07                   ` Narcisa Ana Maria Vasile
  1 sibling, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-01 19:07 UTC (permalink / raw)
  To: Tal Shnaiderman
  Cc: dev, NBU-Contact-Thomas Monjalon, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Wed, Mar 31, 2021 at 01:56:09PM +0000, Tal Shnaiderman wrote:
> > Subject: [PATCH v5 03/10] windows/eal: translate Windows errors to errno-
> > style errors
> > 
> > External email: Use caution opening links or attachments
> > 
> > 
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Add function to translate Windows error codes to errno-style error codes.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
> >  lib/librte_eal/windows/rte_thread.c | 65 ++++++++++++++++++++++-------
> >  1 file changed, 50 insertions(+), 15 deletions(-)
> > 
> > diff --git a/lib/librte_eal/windows/rte_thread.c
> > b/lib/librte_eal/windows/rte_thread.c
> > index b29336cbd..e9181b47f 100644
> > --- a/lib/librte_eal/windows/rte_thread.c
> > +++ b/lib/librte_eal/windows/rte_thread.c
> > @@ -12,6 +12,47 @@ struct eal_tls_key {
> >         DWORD thread_index;
> >  };
> > 
> > +/* Translates the most common error codes related to threads */ static
> > +int rte_thread_translate_win32_error(DWORD error) {
> 
> This DWORD error will always the output of GetLastError()? If so can we move it inside the function?
 
  Yes, I think we can move the call to GetLastError() inside the function, thanks Tal.
> 
> Also, I don't think this is a thread specific function, other implementations can use it in the future, maybe move it to rte_windows.h? 
  
  I think it's better to keep these error-translation functions inside a specific module (threads, memory, etc.).
  The reason for that is that the same error code may mean different things in different modules. When I implemented
  this function I've went through all the Windows threads functions and noted down the type of errors that GetLastError()
  returns for them and what they mean. For a different module, a different set of errors might be more suitable,
  so to keep the translations as semantically compatible as possible to Linux, it's probably better to keep it
  at the module level (threading in this case).
> 
> > +       switch (error) {
> > +       case ERROR_SUCCESS:
> > +               return 0;
> > +
> > +       case ERROR_INVALID_PARAMETER:
> > +               return EINVAL;
> > +
> > +       case ERROR_INVALID_HANDLE:
> > +               return EFAULT;
> > +
> > +       case ERROR_NOT_ENOUGH_MEMORY:
> > +       /* FALLTHROUGH */
> > +       case ERROR_NO_SYSTEM_RESOURCES:
> > +               return ENOMEM;
> > +
> > +       case ERROR_PRIVILEGE_NOT_HELD:
> > +       /* FALLTHROUGH */
> > +       case ERROR_ACCESS_DENIED:
> > +               return EACCES;
> > +
> > +       case ERROR_ALREADY_EXISTS:
> > +               return EEXIST;
> > +
> > +       case ERROR_POSSIBLE_DEADLOCK:
> > +               return EDEADLK;
> > +
> > +       case ERROR_INVALID_FUNCTION:
> > +       /* FALLTHROUGH */
> > +       case ERROR_CALL_NOT_IMPLEMENTED:
> > +               return ENOSYS;
> > +
> > +       default:
> > +               return EINVAL;
> > +       }
> > +
> > +       return EINVAL;
> > +}
> > +
> > @@ -143,7 +178,7 @@ rte_thread_value_get(rte_thread_key key)  {
> >         void *output;
> > 
> 
> This function is missing the change to rte_thread_translate_win32_error.
> Aldo need to change function docu.
  
  Thanks, will fix and send v6.
> 
> > -       if (!key) {
> > +       if (key == NULL) {
> >                 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
> >                 rte_errno = EINVAL;
> >                 return NULL;
> > --
> > 2.30.0.vfs.0.2

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading
  2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-04-03  1:38                 ` Narcisa Ana Maria Vasile
  2021-04-03  1:38                   ` [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                                     ` (11 more replies)
  0 siblings, 12 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  windows/eal: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +--
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |  36 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 +-
 lib/librte_eal/common/eal_common_thread.c     |  43 +-
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_internal_cfg.h      |   2 +
 lib/librte_eal/common/eal_options.h           |   2 +
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +-
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/common/rte_thread.c            | 342 +++++++++++
 lib/librte_eal/freebsd/eal.c                  |  37 +-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/include/rte_thread.h           | 342 ++++++++++-
 lib/librte_eal/include/rte_thread_types.h     |  20 +
 lib/librte_eal/linux/eal.c                    |  42 +-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  20 +
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  92 ---
 lib/librte_eal/version.map                    |  21 +
 lib/librte_eal/windows/eal.c                  |  26 +-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_lcore.c            | 170 ++++--
 lib/librte_eal/windows/eal_thread.c           |  24 +-
 lib/librte_eal/windows/eal_windows.h          |  20 +-
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------
 .../include/rte_windows_thread_types.h        |  19 +
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_eal/windows/rte_thread.c           | 532 +++++++++++++++++-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 +-
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++--
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2048 insertions(+), 934 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
@ 2021-04-03  1:38                   ` Narcisa Ana Maria Vasile
  2021-04-29  0:50                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                     ` (10 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add the thread identifier type.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 101 ++++++++++++++++++
 lib/librte_eal/include/rte_thread.h           |  45 ++++++--
 lib/librte_eal/include/rte_thread_types.h     |  12 +++
 .../include/rte_windows_thread_types.h        |  12 +++
 lib/librte_eal/windows/rte_thread.c           |  13 +++
 5 files changed, 174 insertions(+), 9 deletions(-)
 create mode 100644 lib/librte_eal/common/rte_thread.c
 create mode 100644 lib/librte_eal/include/rte_thread_types.h
 create mode 100644 lib/librte_eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
new file mode 100644
index 000000000..5ec382949
--- /dev/null
+++ b/lib/librte_eal/common/rte_thread.c
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	return pthread_self();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1, t2);
+}
+
+int
+rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_thread_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_key_delete(rte_thread_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_value_set(rte_thread_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_value_get(rte_thread_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 8be8ed8f3..cbc07f739 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_os.h>
@@ -20,6 +21,13 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -27,6 +35,31 @@ typedef struct eal_tls_key *rte_thread_key;
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
@@ -63,9 +96,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +111,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +126,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
new file mode 100644
index 000000000..19fb85e38
--- /dev/null
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+typedef pthread_t                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 000000000..ebd3d9e8f
--- /dev/null
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+typedef DWORD                       rte_thread_t;
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 667287c38..940d9c653 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,18 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1 == t2 ? 1 : 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-04-03  1:38                   ` [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-29  0:50                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority

Implement functions for managing thread attributes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 53 ++++++++++++
 lib/librte_eal/include/rte_thread.h           | 82 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/librte_eal/windows/rte_thread.c           | 56 +++++++++++++
 5 files changed, 197 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 5ec382949..0bd1b115d 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,59 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index cbc07f739..bfdd8e1b1 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -28,6 +28,19 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,
+	/*
+	 * This enum can be extended to allow more priority levels.
+	 */
+};
+
+typedef struct {
+	enum rte_thread_priority priority;
+	rte_cpuset_t cpuset;
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -60,6 +73,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr;
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+				 rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+				 enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 19fb85e38..a884daf17 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 typedef pthread_t                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index ebd3d9e8f..8cb4b3856 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,6 +7,9 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 typedef DWORD                       rte_thread_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 940d9c653..b29336cbd 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -24,6 +24,62 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	if (attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to init thread attributes, invalid parameter\n");
+		return EINVAL;
+	}
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
  2021-04-03  1:38                   ` [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-29  0:50                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                     ` (8 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/include/rte_thread.h |  5 +-
 lib/librte_eal/windows/rte_thread.c | 75 ++++++++++++++++++++++-------
 2 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index bfdd8e1b1..2d7b3bc05 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -221,9 +221,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index b29336cbd..ecd2f810f 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -12,6 +12,51 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int rte_thread_translate_win32_error(void)
+{
+	DWORD error = 0;
+
+	error = GetLastError();
+
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+
+	default:
+		return EINVAL;
+	}
+
+	return EINVAL;
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -87,15 +132,13 @@ rte_thread_key_create(rte_thread_key *key,
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
 		RTE_LOG_WIN32_ERR("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error();
 	}
 	return 0;
 }
@@ -103,16 +146,14 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
 		RTE_LOG_WIN32_ERR("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error();
 	}
 	free(key);
 	return 0;
@@ -123,17 +164,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
 		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return rte_thread_translate_win32_error();
 	}
 	return 0;
 }
@@ -142,16 +181,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	int ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
+	ret = rte_thread_translate_win32_error();
+	if (ret != 0) {
 		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+		rte_errno = ret;
 		return NULL;
 	}
 	return output;
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 04/10] eal: implement functions for thread affinity management
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (2 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-05-02  0:41                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                     ` (7 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c   |  13 ++
 lib/librte_eal/include/rte_thread.h  |  41 +++++++
 lib/librte_eal/windows/eal_lcore.c   | 170 +++++++++++++++++++--------
 lib/librte_eal/windows/eal_windows.h |  10 ++
 lib/librte_eal/windows/rte_thread.c  | 132 ++++++++++++++++++++-
 5 files changed, 318 insertions(+), 48 deletions(-)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 0bd1b115d..4f93e3ff1 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -29,6 +29,19 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1, t2);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id, cpuset_size, cpuset);
+}
+
+int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 2d7b3bc05..4b1e3dfe8 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -73,6 +73,47 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset_size
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset_size
+ *    Size of the cpu set.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+				  rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
index a85149be9..023c5c895 100644
--- a/lib/librte_eal/windows/eal_lcore.c
+++ b/lib/librte_eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -28,13 +27,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -48,13 +49,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -79,57 +178,27 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
-		}
+		if (eal_check_for_duplicate_numa(info))
+			break;
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -139,7 +208,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -165,3 +234,12 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	if (cpu_index < CPU_SETSIZE)
+		return &cpu_map.cpus[cpu_index];
+
+	return NULL;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index 478accc1b..dc5dc8240 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index ecd2f810f..2fa130b1f 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -4,9 +4,9 @@
  */
 
 #include <rte_common.h>
-#include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -69,6 +69,134 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1 == t2 ? 1 : 0;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+			    size_t cpuset_size,
+			    const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
+			rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL || cpuset_size < sizeof(*cpuset)) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 05/10] eal: implement thread priority management functions
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (3 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                     ` (6 subsequent siblings)
  11 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 25 ++++++++++
 lib/librte_eal/include/rte_thread.h | 17 +++++++
 lib/librte_eal/windows/rte_thread.c | 76 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 4f93e3ff1..26c5b1f3c 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -42,6 +42,31 @@ int rte_thread_get_affinity_by_id(rte_thread_t threadid, size_t cpuset_size,
 	return pthread_getaffinity_np(threadid, cpuset_size, cpuset);
 }
 
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int policy;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+
+
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+		policy = SCHED_RR;
+		param.sched_priority = priority;
+	} else if (priority == RTE_THREAD_PRIORITY_NORMAL) {
+		policy = SCHED_OTHER;
+		param.sched_priority = priority;
+	} else {
+		RTE_LOG(DEBUG, EAL, "Invalid priority to set."
+				    "Defaulting to priority 'normal'.\n");
+		policy = SCHED_OTHER;
+	}
+
+	return pthread_setschedparam(thread_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 4b1e3dfe8..f95efb319 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -114,6 +114,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 				  rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 2fa130b1f..f61103bbc 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -197,6 +197,82 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	DWORD priority_class = NORMAL_PRIORITY_CLASS;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	switch (priority) {
+
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		priority_class = REALTIME_PRIORITY_CLASS;
+		break;
+
+	case RTE_THREAD_PRIORITY_NORMAL:
+	/* FALLTHROUGH */
+	default:
+		priority_class = NORMAL_PRIORITY_CLASS;
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+		break;
+	}
+
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("get_process_handle_from_thread_handle()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, priority)) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 06/10] eal: add thread lifetime management
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (4 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-29 20:44                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                     ` (5 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c  | 110 ++++++++++++++++++++++++
 lib/librte_eal/include/rte_thread.h |  53 ++++++++++++
 lib/librte_eal/windows/rte_thread.c | 125 ++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 26c5b1f3c..29d38d193 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -120,6 +120,116 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(thread_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index f95efb319..fa643433a 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -200,6 +200,59 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 				 enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index f61103bbc..86bbd7bc2 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -329,6 +329,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+
+	thread_handle = CreateThread(NULL, 0,
+				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,
+				args, 0, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("CreateThread()");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = rte_thread_translate_win32_error();
+				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = rte_thread_translate_win32_error();
+			RTE_LOG_WIN32_ERR("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
+	if (thread_handle == NULL) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 07/10] eal: implement functions for mutex management
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (5 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-30 17:47                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                     ` (4 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 24 +++++++++
 lib/librte_eal/include/rte_thread.h           | 53 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  3 ++
 .../include/rte_windows_thread_types.h        |  1 +
 lib/librte_eal/windows/rte_thread.c           | 28 ++++++++++
 5 files changed, 109 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 29d38d193..8e963ed65 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -220,6 +220,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index fa643433a..4ec7feca8 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -240,6 +240,58 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
@@ -259,6 +311,7 @@ int rte_thread_cancel(rte_thread_t thread_id);
  *
  * @param cpusetp
  *   Pointer to CPU affinity to set.
+ *
  * @return
  *   On success, return 0; otherwise return -1;
  */
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index a884daf17..37bc7af2b 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,9 +7,12 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
 #define EAL_THREAD_PRIORITY_NORMAL               0
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
 
 typedef pthread_t                       rte_thread_t;
+typedef pthread_mutex_t                 rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 8cb4b3856..47c6b2664 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -11,5 +11,6 @@
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
+typedef CRITICAL_SECTION            rte_thread_mutex_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index 86bbd7bc2..c1221c2ea 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -421,6 +421,34 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 08/10] eal: implement functions for thread barrier management
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (6 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-30 18:06                     ` Dmitry Kozlyuk
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                     ` (3 subsequent siblings)
  11 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/rte_thread.c            | 16 +++++++
 lib/librte_eal/include/rte_thread.h           | 46 +++++++++++++++++++
 lib/librte_eal/include/rte_thread_types.h     |  2 +
 .../include/rte_windows_thread_types.h        |  3 ++
 lib/librte_eal/windows/rte_thread.c           | 27 +++++++++++
 5 files changed, 94 insertions(+)

diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
index 8e963ed65..d23d3b868 100644
--- a/lib/librte_eal/common/rte_thread.c
+++ b/lib/librte_eal/common/rte_thread.c
@@ -244,6 +244,22 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	return pthread_barrier_init(barrier, NULL, count);
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_wait(barrier);
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	return pthread_barrier_destroy(barrier);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
index 4ec7feca8..ddde3f3f8 100644
--- a/lib/librte_eal/include/rte_thread.h
+++ b/lib/librte_eal/include/rte_thread.h
@@ -292,6 +292,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
index 37bc7af2b..b055bbf67 100644
--- a/lib/librte_eal/include/rte_thread_types.h
+++ b/lib/librte_eal/include/rte_thread_types.h
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
 #define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
 
 #define EAL_THREAD_PRIORITY_NORMAL               0
@@ -14,5 +15,6 @@
 
 typedef pthread_t                       rte_thread_t;
 typedef pthread_mutex_t                 rte_thread_mutex_t;
+typedef pthread_barrier_t               rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
index 47c6b2664..b6209e6eb 100644
--- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
+++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
@@ -7,10 +7,13 @@
 
 #include <rte_windows.h>
 
+#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
+
 #define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
 #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
 
 typedef DWORD                       rte_thread_t;
 typedef CRITICAL_SECTION            rte_thread_mutex_t;
+typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
 
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
index c1221c2ea..62849fc61 100644
--- a/lib/librte_eal/windows/rte_thread.c
+++ b/lib/librte_eal/windows/rte_thread.c
@@ -449,6 +449,33 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+
+	if (!InitializeSynchronizationBarrier(barrier, count, -1)) {
+		ret = rte_thread_translate_win32_error();
+		RTE_LOG_WIN32_ERR("InitializeSynchronizationBarrier()");
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	return EnterSynchronizationBarrier(barrier,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	DeleteSynchronizationBarrier(barrier);
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 09/10] eal: add EAL argument for setting thread priority
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (7 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
                                     ` (2 subsequent siblings)
  11 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can select the thread priority to be either 'normal'
or 'critical':
--thread-prio normal
--thread-prio realtime

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/librte_eal/common/eal_common_options.c | 28 +++++++++++++++++++++-
 lib/librte_eal/common/eal_internal_cfg.h   |  2 ++
 lib/librte_eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 622c7bc42..287a89a75 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -106,6 +106,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1383,6 +1384,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1796,7 +1815,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2059,6 +2084,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 51dbe86e2..7ab1d0008 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -93,6 +93,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 7b348e707..9f5b209f6 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v6 10/10] Enable the new EAL thread API
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (8 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-04-03  1:39                   ` Narcisa Ana Maria Vasile
  2021-04-12  7:56                   ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading David Marchand
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
  11 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-03  1:39 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   6 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   6 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |   6 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb/pf/base/dlb_osdep.h         |   2 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   2 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  24 +--
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/hns3/hns3_ethdev.h                |   2 +-
 drivers/net/hns3/hns3_ethdev_vf.c             |   2 +-
 drivers/net/hns3/hns3_mbx.c                   |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   6 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  22 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   8 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  36 ++--
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  67 +++----
 examples/kni/main.c                           |   6 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  10 +-
 lib/librte_eal/common/eal_common_options.c    |   8 +-
 lib/librte_eal/common/eal_common_proc.c       |  48 ++---
 lib/librte_eal/common/eal_common_thread.c     |  43 ++--
 lib/librte_eal/common/eal_common_trace.c      |   2 +-
 lib/librte_eal/common/eal_private.h           |   2 +-
 lib/librte_eal/common/malloc_mp.c             |  32 +--
 lib/librte_eal/common/meson.build             |   1 +
 lib/librte_eal/freebsd/eal.c                  |  37 +++-
 lib/librte_eal/freebsd/eal_alarm.c            |  12 +-
 lib/librte_eal/freebsd/eal_interrupts.c       |   4 +-
 lib/librte_eal/freebsd/eal_thread.c           |   8 +-
 lib/librte_eal/include/meson.build            |   1 +
 lib/librte_eal/include/rte_lcore.h            |   8 +-
 lib/librte_eal/include/rte_per_lcore.h        |   2 -
 lib/librte_eal/linux/eal.c                    |  42 +++-
 lib/librte_eal/linux/eal_alarm.c              |  10 +-
 lib/librte_eal/linux/eal_interrupts.c         |   4 +-
 lib/librte_eal/linux/eal_thread.c             |   8 +-
 lib/librte_eal/linux/eal_timer.c              |   2 +-
 lib/librte_eal/rte_eal_exports.def            |  20 ++
 lib/librte_eal/unix/meson.build               |   1 -
 lib/librte_eal/unix/rte_thread.c              |  92 ---------
 lib/librte_eal/version.map                    |  21 ++
 lib/librte_eal/windows/eal.c                  |  26 ++-
 lib/librte_eal/windows/eal_interrupts.c       |   6 +-
 lib/librte_eal/windows/eal_thread.c           |  24 +--
 lib/librte_eal/windows/eal_windows.h          |  10 -
 lib/librte_eal/windows/include/meson.build    |   1 +
 lib/librte_eal/windows/include/pthread.h      | 186 ------------------
 lib/librte_eal/windows/include/sched.h        |   2 +-
 lib/librte_eal/windows/meson.build            |   7 +-
 lib/librte_ethdev/rte_ethdev.c                |   4 +-
 lib/librte_ethdev/rte_ethdev_core.h           |   3 +-
 lib/librte_ethdev/rte_flow.c                  |   4 +-
 .../rte_event_eth_rx_adapter.c                |   6 +-
 lib/librte_vhost/fd_man.c                     |  40 ++--
 lib/librte_vhost/fd_man.h                     |   6 +-
 lib/librte_vhost/socket.c                     | 124 ++++++------
 lib/librte_vhost/vhost.c                      |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 659 insertions(+), 856 deletions(-)
 delete mode 100644 lib/librte_eal/unix/rte_thread.c
 delete mode 100644 lib/librte_eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index 27f1b1c0e..ff284335a 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 #endif
 #endif
 
@@ -127,7 +127,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
-		pthread_create(&thread, NULL, &send_pkts, NULL);
+		rte_thread_create(&thread, NULL, &send_pkts, NULL);
 #endif
 #endif
 
@@ -137,7 +137,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fc..c507e423e 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a..3d9663f5e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d06..ce79d9c17 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 66a2edcc4..8db5bd725 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -258,6 +258,10 @@ else # for 32-bit we need smaller reserved memory areas
 	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da..a9e6013ff 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,11 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a..dc5f02bec 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681c..6d2d10cdf 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1..c826ad0c1 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -92,10 +92,10 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(),
+					    sizeof(cpu_set_t), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index ec3c23751..d2bda960f 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -73,7 +73,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -833,9 +833,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -855,13 +855,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb/pf/base/dlb_osdep.h b/drivers/event/dlb/pf/base/dlb_osdep.h
index dee20660e..cc22b85d6 100644
--- a/drivers/event/dlb/pf/base/dlb_osdep.h
+++ b/drivers/event/dlb/pf/base/dlb_osdep.h
@@ -208,7 +208,7 @@ static void *dlb_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb_hw *hw)
 {
 	struct dlb_dev *dlb_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb_dev = container_of(hw, struct dlb_dev, hw);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index aa101a49a..b002dc774 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 6e44a21c6..f7a750331 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -179,7 +179,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -670,7 +670,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -681,7 +681,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -719,7 +719,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -745,7 +745,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -774,9 +774,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -942,9 +942,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 9dea5facb..5e093166d 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -563,12 +563,12 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
 		 */
-		if (pthread_create(&thread, NULL,
+		if (rte_thread_create(&thread, NULL,
 				   ark_pktgen_delay_start, ark->pg)) {
 			ARK_PMD_LOG(ERR, "Could not create pktgen "
 				    "starter thread\n");
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f..96b7da3ac 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f32..93e41aa26 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405..a6f576dab 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b..197c72290 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876..e6f252e09 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729f..cfd436fa6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12..c17f9a8b9 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695a..5f3d9b360 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec19..1e1d6358d 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 05f880427..1176004d8 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -533,8 +533,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -693,7 +693,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -747,18 +747,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -944,10 +944,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3..a50511047 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 2bd889b15..78c7977a9 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1043,7 +1043,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1053,20 +1053,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1449,14 +1449,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1538,13 +1538,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1577,14 +1577,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4066,7 +4066,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4074,7 +4074,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4244,7 +4244,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4259,7 +4259,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5048,25 +5048,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5844,14 +5844,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d..e1d980cf9 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index b224a7d2c..3f22a5511 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef9..455d83bef 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061..88d64d703 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd683..26c3e7551 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea..cb6bbcad6 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83..f06bd2b27 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2..1115afa81 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index ac255a3ff..3ebd21c11 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -439,7 +439,7 @@ struct hns3_hw {
 	struct hns3_cmq cmq;
 	struct hns3_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hns3_mbx_arq_ring arq;         /* mailbox async rx queue */
-	pthread_t irq_thread_id;
+	rte_thread_t irq_thread_id;
 	struct hns3_mac mac;
 	unsigned int secondary_cnt; /* Number of secondary processes init'd. */
 	struct hns3_tqp_stats tqp_stats;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 6c3ddcc50..ae1498008 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1110,7 +1110,7 @@ hns3vf_interrupt_handler(void *param)
 	uint32_t clearval;
 
 	if (hw->irq_thread_id == 0)
-		hw->irq_thread_id = pthread_self();
+		hw->irq_thread_id = rte_thread_self();
 
 	/* Disable interrupt */
 	hns3vf_disable_irq0(hw);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 61d15845e..34d2458b1 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -101,7 +101,7 @@ hns3_get_mbx_resp(struct hns3_hw *hw, uint16_t code0, uint16_t code1,
 		 * Sending mbox in the interrupt thread cannot wait for the
 		 * response, so polling the mbox response on the irq thread.
 		 */
-		if (pthread_equal(hw->irq_thread_id, pthread_self())) {
+		if (rte_thread_equal(hw->irq_thread_id, rte_thread_self())) {
 			in_irq = true;
 			hns3_poll_all_sync_msg();
 		} else {
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 476fd4906..66bc7d683 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -152,7 +152,7 @@ static void
 start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 {
 	struct ice_dcf_reset_event_param *param;
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
@@ -165,7 +165,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 	param->vfr = vfr;
 	param->vf_id = vf_id;
 
-	ret = pthread_create(&thread, NULL,
+	ret = rte_thread_create(&thread, NULL,
 			     ice_dcf_vsi_update_service_handler, param);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to start the thread for reset handling");
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 589d9fa58..97e36a2e0 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 31faff066..f872ed14b 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4146,7 +4146,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	pthread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca2..272fdcfb8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549..3518b913e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 2d5bcab4c..6fa19febb 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2504,7 +2504,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 3538cc8c2..a98388ce5 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -181,7 +181,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -904,7 +904,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1031,11 +1031,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1067,7 +1067,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1098,7 +1098,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1129,11 +1129,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2256,7 +2256,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 6faba4fbb..515c21cfa 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -633,7 +633,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index e8d632ad2..2a149f5bf 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -904,7 +904,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -920,7 +920,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -947,7 +947,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -955,7 +955,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index c4d579072..229bad3ea 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_thread_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 6f3927614..956e92d68 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -226,7 +226,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b539928..f0cb71c93 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8..1004ec289 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index d0776739a..97e67b7df 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -142,7 +142,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -160,7 +160,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -184,7 +184,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -205,12 +205,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -225,7 +225,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -248,11 +248,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -379,7 +379,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -404,7 +404,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -490,7 +490,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -795,13 +795,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -811,7 +811,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -836,7 +836,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 7fd4622f0..8f5e9869a 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -55,7 +55,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 05d79bfcc..6f97695e0 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -526,7 +526,7 @@ ifpga_monitor_start_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 0) {
-		ret = pthread_create(&ifpga_monitor_start_thread,
+		ret = rte_thread_create(&ifpga_monitor_start_thread,
 			NULL,
 			ifpga_rawdev_gsd_handle, NULL);
 		if (ret) {
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 39237aecf..6ff8dd123 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -50,7 +50,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -77,7 +77,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -87,7 +87,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -96,7 +96,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -110,7 +110,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -120,7 +120,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -496,7 +496,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, notify_relay,
+	ret = rte_thread_create(&internal->tid, NULL, notify_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create notify relay pthread.");
@@ -508,11 +508,9 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -799,7 +797,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 {
 	int ret;
 
-	ret = pthread_create(&internal->tid, NULL, vring_relay,
+	ret = rte_thread_create(&internal->tid, NULL, vring_relay,
 			(void *)internal);
 	if (ret) {
 		DRV_LOG(ERR, "failed to create ring relay pthread.");
@@ -811,11 +809,9 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
 	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
 	internal->tid = 0;
 
@@ -1245,9 +1241,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1285,9 +1281,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 898e50f80..bcb744f5b 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -764,10 +764,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -798,7 +798,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -807,7 +807,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -816,7 +816,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index d93b430c9..568b84c3f 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 404e135d5..ebb53f4b1 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -247,17 +247,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -281,13 +281,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -297,7 +297,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -313,7 +313,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -332,7 +332,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -347,13 +347,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -369,7 +369,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -415,7 +415,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -502,47 +502,39 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+		rte_thread_attr_init(&attr);
+		CPU_ZERO(&cpuset);
+		if (priv->event_core != -1)
+			CPU_SET(priv->event_core, &cpuset);
+		else
+			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr,
+					RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
 			return -1;
 		}
-		CPU_ZERO(&cpuset);
-		if (priv->event_core != -1)
-			CPU_SET(priv->event_core, &cpuset);
-		else
-			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_setaffinity_np(priv->timer_tid,
-					     sizeof(cpuset), &cpuset);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread affinity.");
-			goto error;
-		}
 		snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
 		ret = pthread_setname_np(priv->timer_tid, name);
 		if (ret) {
@@ -569,7 +561,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -586,8 +577,8 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
 	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
 	priv->timer_tid = 0;
 }
diff --git a/examples/kni/main.c b/examples/kni/main.c
index fe93b8618..d29cbf7ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 2ca7d98c5..c3b2273ef 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1635,7 +1635,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index 5c6407160..e1a712045 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, sizeof(cpu_set_t), &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features, protocol_features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring, inflight_shmfd;
 
@@ -685,7 +685,7 @@ new_device(int vid)
 	/* start polling vring */
 	worker_thread_status = WORKER_STATE_START;
 	fprintf(stdout, "New Device %s, Device ID %d\n", path, vid);
-	if (pthread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
+	if (rte_thread_create(&tid, NULL, &ctrlr_worker, ctrlr) < 0) {
 		fprintf(stderr, "Worker Thread Started Failed\n");
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 287a89a75..839d837f2 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -1843,8 +1843,8 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t),  &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1872,8 +1872,8 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(),
+					  sizeof(rte_cpuset_t), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
index 6d1af3c0e..6eb2bbb3a 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c
index 73a055902..4cd09d230 100644
--- a/lib/librte_eal/common/eal_common_thread.c
+++ b/lib/librte_eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,9 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+					sizeof(rte_cpuset_t), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,7 +168,7 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 };
 
 static void *ctrl_thread_init(void *arg)
@@ -184,9 +183,9 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
@@ -194,8 +193,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -211,9 +210,9 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->start_routine = start_routine;
 	params->arg = arg;
 
-	pthread_barrier_init(&params->configured, NULL, 2);
+	rte_thread_barrier_init(&params->configured, 2);
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, params);
 	if (ret != 0) {
 		free(params);
 		return -ret;
@@ -226,26 +225,26 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, sizeof(*cpuset), cpuset);
 	if (ret)
 		goto fail;
 
-	ret = pthread_barrier_wait(&params->configured);
-	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
-		pthread_barrier_destroy(&params->configured);
+	ret = rte_thread_barrier_wait(&params->configured);
+	if (ret == RTE_THREAD_BARRIER_SERIAL_THREAD) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 
 	return 0;
 
 fail:
-	if (PTHREAD_BARRIER_SERIAL_THREAD ==
-	    pthread_barrier_wait(&params->configured)) {
-		pthread_barrier_destroy(&params->configured);
+	if (RTE_THREAD_BARRIER_SERIAL_THREAD ==
+	    rte_thread_barrier_wait(&params->configured)) {
+		rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
-	pthread_cancel(*thread);
-	pthread_join(*thread, NULL);
+	rte_thread_cancel(*thread);
+	rte_thread_join(*thread, NULL);
 	return -ret;
 }
 
@@ -266,7 +265,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), sizeof(cpuset),
 			&cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 24e27387b..6df4a0127 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b8a0d2002..d5a6abe9a 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index c7101b32d..fdc3a2cfe 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build
index 70bd854fe..4cd4e8e70 100644
--- a/lib/librte_eal/common/meson.build
+++ b/lib/librte_eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
 	'rte_random.c',
 	'rte_reciprocal.c',
 	'rte_service.c',
+	'rte_thread.c',
 	'rte_version.c',
 )
 
diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c
index 32442e5ba..0960dc90e 100644
--- a/lib/librte_eal/freebsd/eal.c
+++ b/lib/librte_eal/freebsd/eal.c
@@ -663,7 +663,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -686,7 +686,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -850,7 +850,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,6 +873,21 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -878,8 +901,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -889,10 +914,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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_alarm.c b/lib/librte_eal/freebsd/eal_alarm.c
index c38b2e04f..e5d7b130b 100644
--- a/lib/librte_eal/freebsd/eal_alarm.c
+++ b/lib/librte_eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/freebsd/eal_interrupts.c b/lib/librte_eal/freebsd/eal_interrupts.c
index 72eeacbc1..de5d2b733 100644
--- a/lib/librte_eal/freebsd/eal_interrupts.c
+++ b/lib/librte_eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -725,5 +725,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c
index 1dce9b04f..082a66917 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 3969cf4ac..0b6feb377 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
 	'rte_string_fns.h',
 	'rte_tailq.h',
 	'rte_thread.h',
+	'rte_thread_types.h',
 	'rte_time.h',
 	'rte_trace.h',
 	'rte_trace_point.h',
diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h
index 1550b75da..d5e004105 100644
--- a/lib/librte_eal/include/rte_lcore.h
+++ b/lib/librte_eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/librte_eal/include/rte_per_lcore.h b/lib/librte_eal/include/rte_per_lcore.h
index eaedf0cb3..025d97f96 100644
--- a/lib/librte_eal/include/rte_per_lcore.h
+++ b/lib/librte_eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c
index abbb53774..76f2daa26 100644
--- a/lib/librte_eal/linux/eal.c
+++ b/lib/librte_eal/linux/eal.c
@@ -958,7 +958,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -986,7 +986,7 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1214,7 +1214,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			sizeof(rte_cpuset_t),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1228,6 +1236,23 @@ rte_eal_init(int argc, char **argv)
 		config->main_lcore, (uintptr_t)thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1241,9 +1266,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1255,11 +1282,6 @@ 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_alarm.c b/lib/librte_eal/linux/eal_alarm.c
index 3252c6fa5..fef22a347 100644
--- a/lib/librte_eal/linux/eal_alarm.c
+++ b/lib/librte_eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/librte_eal/linux/eal_interrupts.c b/lib/librte_eal/linux/eal_interrupts.c
index 1dd994bd1..bc38055b8 100644
--- a/lib/librte_eal/linux/eal_interrupts.c
+++ b/lib/librte_eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1558,5 +1558,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c
index 83c2034b9..bd447d6a2 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -73,11 +73,11 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -164,7 +164,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/lib/librte_eal/linux/eal_timer.c b/lib/librte_eal/linux/eal_timer.c
index 7cf15caba..b4099a0aa 100644
--- a/lib/librte_eal/linux/eal_timer.c
+++ b/lib/librte_eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index c32007754..00752701f 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -330,6 +330,26 @@ EXPORTS
 	rte_thread_value_get
 	rte_thread_value_set
 
+	rte_thread_mutex_lock
+	rte_thread_mutex_unlock
+	rte_thread_mutex_init
+	rte_thread_mutex_destroy
+	rte_thread_create
+	rte_thread_set_affinity_by_id
+	rte_thread_get_affinity_by_id
+	rte_thread_set_priority
+	rte_thread_attr_init
+	rte_thread_attr_set_affinity
+	rte_thread_attr_get_affinity
+	rte_thread_attr_set_priority
+	rte_thread_join
+	rte_thread_self
+	rte_thread_equal
+	rte_thread_barrier_init
+	rte_thread_barrier_wait
+	rte_thread_barrier_destroy
+	rte_thread_cancel
+
 	rte_mem_lock
 	rte_mem_map
 	rte_mem_page_size
diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build
index 71221b84a..d3af6b6fe 100644
--- a/lib/librte_eal/unix/meson.build
+++ b/lib/librte_eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
 	'eal_file.c',
 	'eal_unix_memory.c',
 	'eal_unix_timer.c',
-	'rte_thread.c',
 )
diff --git a/lib/librte_eal/unix/rte_thread.c b/lib/librte_eal/unix/rte_thread.c
deleted file mode 100644
index c72d619ec..000000000
--- a/lib/librte_eal/unix/rte_thread.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_key_delete(rte_thread_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_value_set(rte_thread_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_value_get(rte_thread_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index e23745ae6..b562ee98d 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,6 +421,27 @@ EXPERIMENTAL {
 	rte_version_release;
 	rte_version_suffix;
 	rte_version_year;
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index 2fc3d6141..faaf00972 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -368,6 +368,28 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -384,7 +406,9 @@ rte_eal_init(int argc, char **argv)
 		lcore_config[i].state = WAIT;
 
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
index 3b8266d38..9839a1fed 100644
--- a/lib/librte_eal/windows/eal_interrupts.c
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -7,7 +7,7 @@
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +76,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -94,7 +94,7 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 
 	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread(%lu)", intr_thread);
 		return -ENOENT;
 	}
 
diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c
index 9c3f6d69f..5ed495562 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -60,11 +60,11 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index dc5dc8240..4b92b198c 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/librte_eal/windows/include/meson.build b/lib/librte_eal/windows/include/meson.build
index b3534b025..7d9b3393e 100644
--- a/lib/librte_eal/windows/include/meson.build
+++ b/lib/librte_eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
deleted file mode 100644
index 9aeab1fa7..000000000
--- a/lib/librte_eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/librte_eal/windows/include/sched.h b/lib/librte_eal/windows/include/sched.h
index ff572b5dc..8f0b3cb71 100644
--- a/lib/librte_eal/windows/include/sched.h
+++ b/lib/librte_eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 42ff5c2d5..ffcddcd0c 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
 	'eal_timer.c',
 	'fnmatch.c',
 	'getopt.c',
-	'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'librte_eal/common/rte_thread.c'
+else
+	sources += 'librte_eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3059aa55b..72db655f6 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,7 +506,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -580,7 +580,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 918a34ed1..580108b95 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -5,7 +5,6 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
 #include <sys/types.h>
 
 /**
@@ -183,7 +182,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index e07e617d7..6b2ff73c7 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -223,14 +223,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index d8c635e99..33d8c7b54 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -121,7 +121,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1302,12 +1302,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 55d4856f9..b97774ccd 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index 3ab5cfdd6..ba58d849e 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 0169d3648..5f41d40ba 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,11 +1122,11 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index c9d1371e4..66129fed0 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -657,7 +657,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -666,7 +666,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -674,12 +674,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 86bc6c88f..d70a716d2 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -34,5 +34,7 @@ option('enable_trace_fp', type: 'boolean', value: false,
 	description: 'enable fast path trace points.')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false,
 	description: 'use HPET timer in EAL')
-- 
2.30.0.vfs.0.2


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (9 preceding siblings ...)
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-04-12  7:56                   ` David Marchand
  2021-04-16 20:30                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
  11 siblings, 1 reply; 290+ messages in thread
From: David Marchand @ 2021-04-12  7:56 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, Thomas Monjalon, Dmitry Kozlyuk, Khoa To, navasile,
	Dmitry Malloy (MESHCHANINOV),
	roretzla, Tal Shnaiderman, Omar Cardona, Bruce Richardson,
	Pallavi Kadam

On Sat, Apr 3, 2021 at 3:39 AM Narcisa Ana Maria Vasile
<navasile@linux.microsoft.com> wrote:
>
> From: Narcisa Vasile <navasile@microsoft.com>
>
> EAL thread API
>
> **Problem Statement**
> DPDK currently uses the pthread interface to create and manage threads.
> Windows does not support the POSIX thread programming model, so it currently
> relies on a header file that hides the Windows calls under
> pthread matched interfaces. Given that EAL should isolate the environment
> specifics from the applications and libraries and mediate
> all the communication with the operating systems, a new EAL interface
> is needed for thread management.
>
> **Goals**
> * Introduce a generic EAL API for threading support that will remove
>   the current Windows pthread.h shim.
> * Replace references to pthread_* across the DPDK codebase with the new
>   RTE_THREAD_* API.
> * Allow users to choose between using the RTE_THREAD_* API or a
>   3rd party thread library through a configuration option.
>
> **Design plan**
> New API main files:
> * rte_thread.h (librte_eal/include)
> * rte_thread_types.h (librte_eal/include)
> * rte_thread_windows_types.h (librte_eal/windows/include)
> * rte_thread.c (librte_eal/windows)
> * rte_thread.c (librte_eal/common)
>
> For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
> a 3rd party thread library, through a meson flag “use_external_thread_lib”.
> By default, this flag is set to FALSE, which means Windows libraries and applications
> will use the RTE_THREAD_* API for managing threads.
>
> If compiling on Windows and the “use_external_thread_lib” is *not* set,
> the following files will be parsed:
> * include/rte_thread.h
> * windows/include/rte_thread_windows_types.h
> * windows/rte_thread.c
> In all other cases, the compilation/parsing includes the following files:
> * include/rte_thread.h
> * include/rte_thread_types.h
> * common/rte_thread.c
>
> **A schematic example of the design**
> --------------------------------------------------
> lib/librte_eal/include/rte_thread.h
> int rte_thread_create();
>
> lib/librte_eal/common/rte_thread.c
> int rte_thread_create()
> {
>         return pthread_create();
> }
>
> lib/librte_eal/windows/rte_thread.c
> int rte_thread_create()
> {
>         return CreateThread();
> }
>
> lib/librte_eal/windows/meson.build
> if get_option('use_external_thread_lib')
>         sources += 'librte_eal/common/rte_thread.c'
> else
>         sources += 'librte_eal/windows/rte_thread.c'
> endif
> -----------------------------------------------------
>
> **Thread attributes**
>
> When or after a thread is created, specific characteristics of the thread
> can be adjusted. Given that the thread characteristics that are of interest
> for DPDK applications are affinity and priority, the following structure
> that represents thread attributes has been defined:
>
> typedef struct
> {
>         enum rte_thread_priority priority;
>         rte_cpuset_t cpuset;
> } rte_thread_attr_t;
>
> The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
> object that will cause the thread to be created with the affinity and priority
> described by the attributes object. If no rte_thread_attr_t is passed
> (parameter is NULL), the default affinity and priority are used.
> An rte_thread_attr_t object can also be set to the default values
> by calling *rte_thread_attr_init()*.
>
> *Priority* is represented through an enum that currently advertises
> two values for priority:
>         - RTE_THREAD_PRIORITY_NORMAL
>         - RTE_THREAD_PRIORITY_REALTIME_CRITICAL
> The enum can be extended to allow for multiple priority levels.
> rte_thread_set_priority      - sets the priority of a thread
> rte_thread_attr_set_priority - updates an rte_thread_attr_t object
>                                with a new value for priority
>
> The user can choose thread priority through an EAL parameter,
> when starting an application.  If EAL parameter is not used,
> the per-platform default value for thread priority is used.
> Otherwise administrator has an option to set one of available options:
>  --thread-prio normal
>  --thread-prio realtime
>
> Example:
> ./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff
>
> *Affinity* is described by the already known “rte_cpuset_t” type.
> rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
>                                    rte_thread_attr_t object
> rte_thread_set/get_affinity      – sets/gets the affinity of a thread
>
> **Errors**
> A translation function that maps Windows error codes to errno-style
> error codes is provided.
>
> **Future work**
> Note that this patchset was focused on introducing new API that will
> remove the Windows pthread.h shim. In DPDK, there are still a few references
> to pthread_* that were not implemented in the shim.
> The long term plan is for EAL to provide full threading support:
> * Adding support for conditional variables
> * Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
> * Static mutex initializers are not used on Windows. If we must continue
>   using them, they need to be platform dependent and an implementation will
>   need to be provided for Windows.

Thanks for taking on this huge work.

There is no review on this series and I don't have time for it.
This is a core part of the EAL API.
Seeing how rc1 is at the end of this week, my recommendation is to
postpone to 21.08.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading
  2021-04-12  7:56                   ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading David Marchand
@ 2021-04-16 20:30                     ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-16 20:30 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, Thomas Monjalon, Dmitry Kozlyuk, Khoa To, navasile,
	Dmitry Malloy (MESHCHANINOV),
	roretzla, Tal Shnaiderman, Omar Cardona, Bruce Richardson,
	Pallavi Kadam

On Mon, Apr 12, 2021 at 09:56:14AM +0200, David Marchand wrote:
> On Sat, Apr 3, 2021 at 3:39 AM Narcisa Ana Maria Vasile
> <navasile@linux.microsoft.com> wrote:
> >
> > From: Narcisa Vasile <navasile@microsoft.com>
> >
> > EAL thread API
> >
> Thanks for taking on this huge work.
> 
> There is no review on this series and I don't have time for it.
> This is a core part of the EAL API.
> Seeing how rc1 is at the end of this week, my recommendation is to
> postpone to 21.08.
> 
  Thanks David! I think we've seen a lot of great contributions recently
  and maintainers had a lot of patches to look at. The reviewers will probably
  have more time to analyze this in the next period.

> 
> -- 
> David Marchand

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-03  1:38                   ` [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-04-29  0:50                     ` Dmitry Kozlyuk
  2021-04-29  7:44                       ` Thomas Monjalon
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-29  0:50 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:38 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add the thread identifier type.
> Add functions for comparing thread ids and obtaining the thread id
> for the current thread.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---

(For the whole series.)
Please summarize and distribute relevant parts of the cover letter to commit
messages. Remember that cover letter doesn't get to commit log. This series
has subtle details that a good commit message should describe.

> diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
> new file mode 100644
> index 000000000..19fb85e38
> --- /dev/null
> +++ b/lib/librte_eal/include/rte_thread_types.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Microsoft Corporation
> + */
> +
> +#ifndef _RTE_THREAD_TYPES_H_
> +#define _RTE_THREAD_TYPES_H_
> +
> +#include <pthread.h>
> +
> +typedef pthread_t                       rte_thread_t;
> +
> +#endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> new file mode 100644
> index 000000000..ebd3d9e8f
> --- /dev/null
> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Microsoft Corporation
> + */
> +
> +#ifndef _RTE_THREAD_TYPES_H_
> +#define _RTE_THREAD_TYPES_H_
> +
> +#include <rte_windows.h>
> +
> +typedef DWORD                       rte_thread_t;
> +
> +#endif /* _RTE_THREAD_TYPES_H_ */

pthread_t type in pthreads-win32 and winpthread is not 32 bit.
DPDK will have different ABI depending on a threading backend used.
Apps must know it at build time then. How do they discover it?
This is worth a warning in commit log and docs.

> diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
> index 667287c38..940d9c653 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -1,5 +1,6 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
>   * Copyright 2021 Mellanox Technologies, Ltd
> + * Copyright(c) 2021 Microsoft Corporation
>   */
>  
>  #include <rte_common.h>
> @@ -11,6 +12,18 @@ struct eal_tls_key {
>  	DWORD thread_index;
>  };
>  
> +rte_thread_t
> +rte_thread_self(void)
> +{
> +	return GetCurrentThreadId();
> +}
> +
> +int
> +rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
> +{
> +	return t1 == t2 ? 1 : 0;
> +}
> +

"a == b" returns (int)0 or (int)1 in C.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-04-29  0:50                     ` Dmitry Kozlyuk
  2021-04-29  7:48                       ` Thomas Monjalon
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-29  0:50 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Implement thread attributes for:
> * thread affinity
> * thread priority
> 
> Implement functions for managing thread attributes.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/librte_eal/common/rte_thread.c            | 53 ++++++++++++
>  lib/librte_eal/include/rte_thread.h           | 82 +++++++++++++++++++
>  lib/librte_eal/include/rte_thread_types.h     |  3 +
>  .../include/rte_windows_thread_types.h        |  3 +
>  lib/librte_eal/windows/rte_thread.c           | 56 +++++++++++++
>  5 files changed, 197 insertions(+)
> 
> diff --git a/lib/librte_eal/common/rte_thread.c b/lib/librte_eal/common/rte_thread.c
> index 5ec382949..0bd1b115d 100644
> --- a/lib/librte_eal/common/rte_thread.c
> +++ b/lib/librte_eal/common/rte_thread.c

Please see a comment to Windows counterpart of this file.

[...]
> diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
> index cbc07f739..bfdd8e1b1 100644
> --- a/lib/librte_eal/include/rte_thread.h
> +++ b/lib/librte_eal/include/rte_thread.h
> @@ -28,6 +28,19 @@ extern "C" {
>  #include <rte_thread_types.h>
>  #endif
>  
> +enum rte_thread_priority {
> +	RTE_THREAD_PRIORITY_NORMAL            = EAL_THREAD_PRIORITY_NORMAL,
> +	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = EAL_THREAD_PRIORITY_REALTIME_CIRTICAL,

Please add Doxygen comments for each new public item in the API.

> +	/*
> +	 * This enum can be extended to allow more priority levels.
> +	 */

This comment is useless: any enum can be extended.
(FYI, recently DPDK eliminated xxx_MAX enum members
just so that apps don't rely on enums not being extended.)

> +};
> +
> +typedef struct {
> +	enum rte_thread_priority priority;
> +	rte_cpuset_t cpuset;
> +} rte_thread_attr_t;
> +
>  /**
>   * TLS key type, an opaque pointer.
>   */
> @@ -60,6 +73,75 @@ rte_thread_t rte_thread_self(void);
>  __rte_experimental
>  int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
>  
> +/**
> + * Initialize the attributes of a thread.
> + * These attributes can be passed to the rte_thread_create() function
> + * that will create a new thread and set its attributes according to attr;

Typo: ";" -> "."

> + *
> + * @param attr
> + *   Thread attributes to initialize.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.
> + */
> +__rte_experimental
> +int rte_thread_attr_init(rte_thread_attr_t *attr);
> +
> +/**
> + * Set the CPU affinity value in the thread attributes pointed to
> + * by 'thread_attr'.
> + *
> + * @param thread_attr
> + *   Points to the thread attributes in which affinity will be updated.
> + *
> + * @param cpuset
> + *   Points to the value of the affinity to be set.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.
> + */
> +__rte_experimental
> +int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
> +				 rte_cpuset_t *cpuset);

This description belongs to another function, doesn't it?
Same for other added functions below. Please double-check comments.

[...]
> diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
> index 19fb85e38..a884daf17 100644
> --- a/lib/librte_eal/include/rte_thread_types.h
> +++ b/lib/librte_eal/include/rte_thread_types.h
> @@ -7,6 +7,9 @@
>  
>  #include <pthread.h>
>  
> +#define EAL_THREAD_PRIORITY_NORMAL               0
> +#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99

Typo: "cirtical" -> "critical"
Are these values chosen arbitrarily?
What do you think of making "enum rte_thread_priority" members just 0 and 1,
then mapping them to OS-specific values in getters/setters?

> +
>  typedef pthread_t                       rte_thread_t;
>  
>  #endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> index ebd3d9e8f..8cb4b3856 100644
> --- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> @@ -7,6 +7,9 @@
>  
>  #include <rte_windows.h>
>  
> +#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
> +#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
> +
>  typedef DWORD                       rte_thread_t;
>  
>  #endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
> index 940d9c653..b29336cbd 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -24,6 +24,62 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
>  	return t1 == t2 ? 1 : 0;
>  }
>  
> +int
> +rte_thread_attr_init(rte_thread_attr_t *attr)
> +{
> +	if (attr == NULL) {
> +		RTE_LOG(DEBUG, EAL,
> +		"Unable to init thread attributes, invalid parameter\n");
> +		return EINVAL;
> +	}

This message doesn't add value for debugging: caller already knows that
attribute initialization failed (that's what function attempts to do) and
that the parameter is invalid (EINVAL).
I'd remove it (same applies below).
If you find it useful to keep, an extra indent missing (also more below).

[...]

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-04-29  0:50                     ` Dmitry Kozlyuk
  2021-04-30  2:39                       ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-29  0:50 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add function to translate Windows error codes to
> errno-style error codes.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>

Commit topic should be "eal/windows", not "windows/eal".

> ---
>  lib/librte_eal/include/rte_thread.h |  5 +-
>  lib/librte_eal/windows/rte_thread.c | 75 ++++++++++++++++++++++-------
>  2 files changed, 60 insertions(+), 20 deletions(-)
> 
> diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
> index bfdd8e1b1..2d7b3bc05 100644
> --- a/lib/librte_eal/include/rte_thread.h
> +++ b/lib/librte_eal/include/rte_thread.h
> @@ -221,9 +221,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
>   *
>   * @return
>   *   On success, value data pointer (can also be NULL).
> - *   On failure, NULL and an error number is set in rte_errno.
> - *   rte_errno can be: EINVAL  - Invalid parameter passed.
> - *                     ENOEXEC - Specific OS error.
> + *   On failure, NULL and a positive error number is set in rte_errno.
> + *
>   */
>  __rte_experimental
>  void *rte_thread_value_get(rte_thread_key key);
> diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
> index b29336cbd..ecd2f810f 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -12,6 +12,51 @@ struct eal_tls_key {
>  	DWORD thread_index;
>  };
>  
> +/* Translates the most common error codes related to threads */
> +static int rte_thread_translate_win32_error(void)

Return type should be on a separate line.

> +{
> +	DWORD error = 0;
> +
> +	error = GetLastError();

You could declare "error" and assign it in one statement.

Don't initialize variables if there's no good initial value:
it prevents compiler to issue a warning if the variable is not assigned a
meaningful value afterwards.

> +
> +	switch (error) {
> +	case ERROR_SUCCESS:
> +		return 0;
> +
> +	case ERROR_INVALID_PARAMETER:
> +		return EINVAL;
> +
> +	case ERROR_INVALID_HANDLE:
> +		return EFAULT;
> +
> +	case ERROR_NOT_ENOUGH_MEMORY:
> +	/* FALLTHROUGH */
> +	case ERROR_NO_SYSTEM_RESOURCES:
> +		return ENOMEM;
> +
> +	case ERROR_PRIVILEGE_NOT_HELD:
> +	/* FALLTHROUGH */
> +	case ERROR_ACCESS_DENIED:
> +		return EACCES;
> +
> +	case ERROR_ALREADY_EXISTS:
> +		return EEXIST;
> +
> +	case ERROR_POSSIBLE_DEADLOCK:
> +		return EDEADLK;
> +
> +	case ERROR_INVALID_FUNCTION:
> +	/* FALLTHROUGH */
> +	case ERROR_CALL_NOT_IMPLEMENTED:
> +		return ENOSYS;
> +
> +	default:
> +		return EINVAL;
> +	}

Default branch is redundant at the end of function.

> +
> +	return EINVAL;
> +}
> +
>  rte_thread_t
>  rte_thread_self(void)
>  {
> @@ -87,15 +132,13 @@ rte_thread_key_create(rte_thread_key *key,
>  	*key = malloc(sizeof(**key));
>  	if ((*key) == NULL) {
>  		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
> -		rte_errno = ENOMEM;
> -		return -1;
> +		return ENOMEM;
>  	}
>  	(*key)->thread_index = TlsAlloc();
>  	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
>  		RTE_LOG_WIN32_ERR("TlsAlloc()");
>  		free(*key);
> -		rte_errno = ENOEXEC;
> -		return -1;
> +		return rte_thread_translate_win32_error();

Logging above can overwrite GetLastError() value.
I suggest splitting rte_thread_translate_win32_error() into translation part
for cases when you have error number already, and a wrapper that calls
GetLastError() to shorten calling code.

Same applies below in this file.

[...]

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-29  0:50                     ` Dmitry Kozlyuk
@ 2021-04-29  7:44                       ` Thomas Monjalon
  2021-04-29 12:05                         ` Kinsella, Ray
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-04-29  7:44 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile, Dmitry Kozlyuk
  Cc: dev, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam, mdr

29/04/2021 02:50, Dmitry Kozlyuk:
> 2021-04-02 18:38 (UTC-0700), Narcisa Ana Maria Vasile:
> > --- /dev/null
> > +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> > @@ -0,0 +1,12 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(c) 2021 Microsoft Corporation
> > + */
> > +
> > +#ifndef _RTE_THREAD_TYPES_H_
> > +#define _RTE_THREAD_TYPES_H_
> > +
> > +#include <rte_windows.h>
> > +
> > +typedef DWORD                       rte_thread_t;
> > +
> > +#endif /* _RTE_THREAD_TYPES_H_ */
> 
> pthread_t type in pthreads-win32 and winpthread is not 32 bit.
> DPDK will have different ABI depending on a threading backend used.
> Apps must know it at build time then. How do they discover it?
> This is worth a warning in commit log and docs.

Not sure this is an acceptable behaviour.
In my opinion, ABI should not vary.
+Cc Ray



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes
  2021-04-29  0:50                     ` Dmitry Kozlyuk
@ 2021-04-29  7:48                       ` Thomas Monjalon
  2021-04-29 15:52                         ` [dpdk-dev] [EXTERNAL] " Tyler Retzlaff
  2021-04-29 16:28                         ` [dpdk-dev] " Dmitry Kozlyuk
  0 siblings, 2 replies; 290+ messages in thread
From: Thomas Monjalon @ 2021-04-29  7:48 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile, Dmitry Kozlyuk
  Cc: dev, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

29/04/2021 02:50, Dmitry Kozlyuk:
> 2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
> > +int
> > +rte_thread_attr_init(rte_thread_attr_t *attr)
> > +{
> > +	if (attr == NULL) {
> > +		RTE_LOG(DEBUG, EAL,
> > +		"Unable to init thread attributes, invalid parameter\n");
> > +		return EINVAL;
> > +	}
> 
> This message doesn't add value for debugging: caller already knows that
> attribute initialization failed (that's what function attempts to do) and
> that the parameter is invalid (EINVAL).
> I'd remove it (same applies below).
> If you find it useful to keep, an extra indent missing (also more below).

Recently in ethdev we added more messages like this for NULL parameters.
I agree it is not a lot useful but I understand that lazy developers may like it ;)



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-29  7:44                       ` Thomas Monjalon
@ 2021-04-29 12:05                         ` Kinsella, Ray
  2021-04-29 16:00                           ` Tyler Retzlaff
  2021-04-29 16:28                           ` Dmitry Kozlyuk
  0 siblings, 2 replies; 290+ messages in thread
From: Kinsella, Ray @ 2021-04-29 12:05 UTC (permalink / raw)
  To: Thomas Monjalon, Narcisa Ana Maria Vasile, Dmitry Kozlyuk
  Cc: dev, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam



On 29/04/2021 08:44, Thomas Monjalon wrote:
> 29/04/2021 02:50, Dmitry Kozlyuk:
>> 2021-04-02 18:38 (UTC-0700), Narcisa Ana Maria Vasile:
>>> --- /dev/null
>>> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
>>> @@ -0,0 +1,12 @@
>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>> + * Copyright(c) 2021 Microsoft Corporation
>>> + */
>>> +
>>> +#ifndef _RTE_THREAD_TYPES_H_
>>> +#define _RTE_THREAD_TYPES_H_
>>> +
>>> +#include <rte_windows.h>
>>> +
>>> +typedef DWORD                       rte_thread_t;
>>> +
>>> +#endif /* _RTE_THREAD_TYPES_H_ */
>>
>> pthread_t type in pthreads-win32 and winpthread is not 32 bit.
>> DPDK will have different ABI depending on a threading backend used.
>> Apps must know it at build time then. How do they discover it?
>> This is worth a warning in commit log and docs.
> 
> Not sure this is an acceptable behaviour.
> In my opinion, ABI should not vary.
> +Cc Ray
> 

So pthread_t on Win32 should just map to the HANDLE datatype.
Which if memory serves is in fact a DWORD on Win32. 
So I suspect that pthreads indirection is probably be just providing a circuitous route to end up in the same place, a HANDLE

IMHO
To absolutely guarantee no ABI change, we ought to be passing back void * not rte_thread_t. 

#ifdef WIN32
/* The primitives for Windows types */
..
typedef HANDLE                apr_os_thread_t; /*becomes pthread_t later*/
..

Ray K

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v6 02/10] eal: add thread attributes
  2021-04-29  7:48                       ` Thomas Monjalon
@ 2021-04-29 15:52                         ` Tyler Retzlaff
  2021-04-30 23:00                           ` Dmitry Kozlyuk
  2021-04-29 16:28                         ` [dpdk-dev] " Dmitry Kozlyuk
  1 sibling, 1 reply; 290+ messages in thread
From: Tyler Retzlaff @ 2021-04-29 15:52 UTC (permalink / raw)
  To: thomas, Narcisa Ana Maria Vasile, Dmitry Kozlyuk
  Cc: dev, Khoa To, Narcisa Ana Maria Vasile, Dmitry Malloy, talshn,
	Omar Cardona, bruce.richardson, david.marchand, Kadam, Pallavi



-----Original Message-----
From: Thomas Monjalon <thomas@monjalon.net> 
Sent: Thursday, April 29, 2021 12:48 AM


29/04/2021 02:50, Dmitry Kozlyuk:
> > 2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
> > > +int
> > > +rte_thread_attr_init(rte_thread_attr_t *attr) {
> > > +	if (attr == NULL) {
> > > +		RTE_LOG(DEBUG, EAL,
> > > +		"Unable to init thread attributes, invalid parameter\n");
> > > +		return EINVAL;
> > > +	}
> > 
> > This message doesn't add value for debugging: caller already knows 
> > that attribute initialization failed (that's what function attempts to 
> > do) and that the parameter is invalid (EINVAL).
> > I'd remove it (same applies below).
> > If you find it useful to keep, an extra indent missing (also more below).

> Recently in ethdev we added more messages like this for NULL parameters.
> I agree it is not a lot useful but I understand that lazy developers may like it ;)

Shouldn't this specific case be an assert?  Unless we are trying to maintain compatibility with existing badly designed semantics.
The whole calling pattern is non-sensible, the caller passes an NULL parameter to a function where the input contract is non-NULL and then proceeds to handle the error by doing what that could possibly be useful exactly?


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-29 12:05                         ` Kinsella, Ray
@ 2021-04-29 16:00                           ` Tyler Retzlaff
  2021-04-29 16:28                           ` Dmitry Kozlyuk
  1 sibling, 0 replies; 290+ messages in thread
From: Tyler Retzlaff @ 2021-04-29 16:00 UTC (permalink / raw)
  To: Kinsella, Ray
  Cc: Thomas Monjalon, Narcisa Ana Maria Vasile, Dmitry Kozlyuk, dev,
	khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Thu, Apr 29, 2021 at 01:05:05PM +0100, Kinsella, Ray wrote:
> 
> 
> On 29/04/2021 08:44, Thomas Monjalon wrote:
> > 29/04/2021 02:50, Dmitry Kozlyuk:
> >> 2021-04-02 18:38 (UTC-0700), Narcisa Ana Maria Vasile:
> >>> --- /dev/null
> >>> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> >>> @@ -0,0 +1,12 @@
> >>> +/* SPDX-License-Identifier: BSD-3-Clause
> >>> + * Copyright(c) 2021 Microsoft Corporation
> >>> + */
> >>> +
> >>> +#ifndef _RTE_THREAD_TYPES_H_
> >>> +#define _RTE_THREAD_TYPES_H_
> >>> +
> >>> +#include <rte_windows.h>
> >>> +
> >>> +typedef DWORD                       rte_thread_t;
> >>> +
> >>> +#endif /* _RTE_THREAD_TYPES_H_ */
> >>
> >> pthread_t type in pthreads-win32 and winpthread is not 32 bit.
> >> DPDK will have different ABI depending on a threading backend used.
> >> Apps must know it at build time then. How do they discover it?
> >> This is worth a warning in commit log and docs.
> > 
> > Not sure this is an acceptable behaviour.
> > In my opinion, ABI should not vary.
> > +Cc Ray
> > 
> 
> So pthread_t on Win32 should just map to the HANDLE datatype.
> Which if memory serves is in fact a DWORD on Win32. 
> So I suspect that pthreads indirection is probably be just providing a circuitous route to end up in the same place, a HANDLE
> 
> IMHO
> To absolutely guarantee no ABI change, we ought to be passing back void * not rte_thread_t. 

agreed, the type should be opaque.

but may i suggest uintptr_t instead since void * still leaks implementation detail.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-29 12:05                         ` Kinsella, Ray
  2021-04-29 16:00                           ` Tyler Retzlaff
@ 2021-04-29 16:28                           ` Dmitry Kozlyuk
  2021-04-30  6:37                             ` Narcisa Ana Maria Vasile
  1 sibling, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-29 16:28 UTC (permalink / raw)
  To: Kinsella, Ray
  Cc: Thomas Monjalon, Narcisa Ana Maria Vasile, dev, khot, navasile,
	dmitrym, roretzla, talshn, ocardona, bruce.richardson,
	david.marchand, pallavi.kadam

2021-04-29 13:05 (UTC+0100), Kinsella, Ray:
> On 29/04/2021 08:44, Thomas Monjalon wrote:
> > 29/04/2021 02:50, Dmitry Kozlyuk:  
> >> 2021-04-02 18:38 (UTC-0700), Narcisa Ana Maria Vasile:  
> >>> --- /dev/null
> >>> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> >>> @@ -0,0 +1,12 @@
> >>> +/* SPDX-License-Identifier: BSD-3-Clause
> >>> + * Copyright(c) 2021 Microsoft Corporation
> >>> + */
> >>> +
> >>> +#ifndef _RTE_THREAD_TYPES_H_
> >>> +#define _RTE_THREAD_TYPES_H_
> >>> +
> >>> +#include <rte_windows.h>
> >>> +
> >>> +typedef DWORD                       rte_thread_t;
> >>> +
> >>> +#endif /* _RTE_THREAD_TYPES_H_ */  
> >>
> >> pthread_t type in pthreads-win32 and winpthread is not 32 bit.
> >> DPDK will have different ABI depending on a threading backend used.
> >> Apps must know it at build time then. How do they discover it?
> >> This is worth a warning in commit log and docs.  
> > 
> > Not sure this is an acceptable behaviour.
> > In my opinion, ABI should not vary.
> > +Cc Ray
> >   
> 
> So pthread_t on Win32 should just map to the HANDLE datatype.
> Which if memory serves is in fact a DWORD on Win32.

DWORD = uint32_t, HANDLE = void*, which are of different size on x64.
I suggest an opaque 64-bit value to fit pthread_t from MinGW's winpthread.
Only pthreads-win32 has a bigger pthread_t, but we don't have to support it.

> So I suspect that pthreads indirection is probably be just providing a circuitous route to end up in the same place, a HANDLE
> 
> IMHO
> To absolutely guarantee no ABI change, we ought to be passing back void * not rte_thread_t. 

Yes. Only I'd use a type-safe version:

	typedef struct rte_thread_tag {
		void *opaque; /* or uintptr_t per Tyler's suggestion */
	} rte_thread_t;


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes
  2021-04-29  7:48                       ` Thomas Monjalon
  2021-04-29 15:52                         ` [dpdk-dev] [EXTERNAL] " Tyler Retzlaff
@ 2021-04-29 16:28                         ` Dmitry Kozlyuk
  1 sibling, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-29 16:28 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: Narcisa Ana Maria Vasile, dev, khot, navasile, dmitrym, roretzla,
	talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

2021-04-29 09:48 (UTC+0200), Thomas Monjalon:
> 29/04/2021 02:50, Dmitry Kozlyuk:
> > 2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:  
> > > +int
> > > +rte_thread_attr_init(rte_thread_attr_t *attr)
> > > +{
> > > +	if (attr == NULL) {
> > > +		RTE_LOG(DEBUG, EAL,
> > > +		"Unable to init thread attributes, invalid parameter\n");
> > > +		return EINVAL;
> > > +	}  
> > 
> > This message doesn't add value for debugging: caller already knows that
> > attribute initialization failed (that's what function attempts to do) and
> > that the parameter is invalid (EINVAL).
> > I'd remove it (same applies below).
> > If you find it useful to keep, an extra indent missing (also more below).  
> 
> Recently in ethdev we added more messages like this for NULL parameters.
> I agree it is not a lot useful but I understand that lazy developers may like it ;)

Messages in 53ef1b34776b ("ethdev: add sanity checks in control APIs")
at least tell why exactly a parameter is invalid and which parameter is it.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 06/10] eal: add thread lifetime management
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-04-29 20:44                     ` Dmitry Kozlyuk
  2021-04-29 21:31                       ` [dpdk-dev] [EXTERNAL] " Dmitry Malloy
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-29 20:44 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
> index f61103bbc..86bbd7bc2 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -329,6 +329,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
>  	return 0;
>  }
>  
> +int
> +rte_thread_create(rte_thread_t *thread_id,
> +		  const rte_thread_attr_t *thread_attr,
> +		  void *(*thread_func)(void *), void *args)
> +{
> +	int ret = 0;
> +	HANDLE thread_handle = NULL;
> +	GROUP_AFFINITY thread_affinity;
> +
> +	thread_handle = CreateThread(NULL, 0,
> +				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,

thread_func returns void* (8 bytes), LPTHREAD_START_ROUTING
returns DWORD (4 byte), is this cast safe?
It seems to be on x86, can't say for ARM64.

> +				args, 0, thread_id);
> +	if (thread_handle == NULL) {
> +		ret = rte_thread_translate_win32_error();
> +		RTE_LOG_WIN32_ERR("CreateThread()");
> +		goto cleanup;
> +	}

After this point, in case of errors the thread remains running,
while the function reports failure. It's better to create the thread
suspended, configure its attributes (destroying the thread on failure), then
resume (start) the thread.

> +
> +	if (thread_attr != NULL) {
> +		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
> +			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
> +			if (ret != 0) {
> +				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
> +				goto cleanup;
> +			}
> +
> +			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
> +				ret = rte_thread_translate_win32_error();
> +				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
> +				goto cleanup;
> +			}
> +		}
> +		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
> +		if (ret != 0) {
> +			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
> +			goto cleanup;
> +		}
> +	}
> +
> +	return 0;
> +
> +cleanup:
> +	if (thread_handle != NULL) {
> +		CloseHandle(thread_handle);
> +		thread_handle = NULL;
> +	}
> +	return ret;
> +}

[...]
> +
> +int
> +rte_thread_cancel(rte_thread_t thread_id)
> +{
> +	int ret = 0;
> +	HANDLE thread_handle = NULL;
> +
> +	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
> +	if (thread_handle == NULL) {
> +		ret = rte_thread_translate_win32_error();
> +		RTE_LOG_WIN32_ERR("OpenThread()");
> +		goto cleanup;
> +	}
> +
> +	/*
> +	 * TODO: Behavior is different between POSIX and Windows threads.
> +	 * POSIX threads wait for a cancellation point.
> +	 * Current Windows emulation kills thread at any point.
> +	 */
> +	ret = TerminateThread(thread_handle, 0);

This is not acceptable.
There is a handful of pthread_cancel() usages in DPDK.
The threads they cancel take spinlocks and mutexes,
so interrupt at arbitrary point may cause a deadlock.

User		Cancellation points	Notes
----		-------------------	-----
net/ipn3ke	libfdt functions?
net/kni		usleep			Linux-only
raw/ifpga	open/read/write/close
vdpa/ifc	read
vdpa/mlx5	usleep, nanosleep
lib/eventdev	rte_epoll_wait		no pthread CP

Possible solutions:

1. Make specific DPDK functions cancellation points for this API and ensure
DPDK users of pthread_cancel() call it.  This way is almost non-invasive,
but it's more work in EAL.

2. Divert from pthread style: add cancellation token concept, so that DPDK
users can check themselves if they're cancelled. This is invasive, but very
explicit and flexible.

> +	if (ret != 0) {
> +		ret = rte_thread_translate_win32_error();
> +		RTE_LOG_WIN32_ERR("TerminateThread()");
> +		goto cleanup;
> +	}
> +
> +cleanup:
> +	if (thread_handle != NULL) {
> +		CloseHandle(thread_handle);
> +		thread_handle = NULL;

This line is not needed.

> +	}
> +	return ret;
> +}
> +
>  int
>  rte_thread_key_create(rte_thread_key *key,
>  		__rte_unused void (*destructor)(void *))



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v6 06/10] eal: add thread lifetime management
  2021-04-29 20:44                     ` Dmitry Kozlyuk
@ 2021-04-29 21:31                       ` Dmitry Malloy
  2021-04-30 17:22                         ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Malloy @ 2021-04-29 21:31 UTC (permalink / raw)
  To: Dmitry Kozlyuk, Narcisa Ana Maria Vasile
  Cc: dev, thomas, Khoa To, Narcisa Ana Maria Vasile, Tyler Retzlaff,
	talshn, Omar Cardona, bruce.richardson, david.marchand, Kadam,
	Pallavi

Thread cancellation is a pain point. Emulating it properly is nearly impossible (without hooking into various OS calls which are supposed to be "cancellation points"). I do like the cancellation token idea, but I'm not sure how existing clients, who rely on existing phtread_cancel() semantic, will react to that - it will require a code re-write. 

How about we defer fixing this to another follow-up change? 

-----Original Message-----
From: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> 
Sent: Thursday, April 29, 2021 1:44 PM
To: Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>
Cc: dev@dpdk.org; thomas <thomas@monjalon.net>; Khoa To <khot@microsoft.com>; Narcisa Ana Maria Vasile <Narcisa.Vasile@microsoft.com>; Dmitry Malloy <dmitrym@microsoft.com>; Tyler Retzlaff <roretzla@microsoft.com>; talshn@nvidia.com; Omar Cardona <ocardona@microsoft.com>; bruce.richardson@intel.com; david.marchand@redhat.com; Kadam, Pallavi <pallavi.kadam@intel.com>
Subject: [EXTERNAL] Re: [PATCH v6 06/10] eal: add thread lifetime management

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> diff --git a/lib/librte_eal/windows/rte_thread.c 
> b/lib/librte_eal/windows/rte_thread.c
> index f61103bbc..86bbd7bc2 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -329,6 +329,131 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
>  	return 0;
>  }
>  
> +int
> +rte_thread_create(rte_thread_t *thread_id,
> +		  const rte_thread_attr_t *thread_attr,
> +		  void *(*thread_func)(void *), void *args) {
> +	int ret = 0;
> +	HANDLE thread_handle = NULL;
> +	GROUP_AFFINITY thread_affinity;
> +
> +	thread_handle = CreateThread(NULL, 0,
> +				(LPTHREAD_START_ROUTINE)(ULONG_PTR)thread_func,

thread_func returns void* (8 bytes), LPTHREAD_START_ROUTING returns DWORD (4 byte), is this cast safe?
It seems to be on x86, can't say for ARM64.

> +				args, 0, thread_id);
> +	if (thread_handle == NULL) {
> +		ret = rte_thread_translate_win32_error();
> +		RTE_LOG_WIN32_ERR("CreateThread()");
> +		goto cleanup;
> +	}

After this point, in case of errors the thread remains running, while the function reports failure. It's better to create the thread suspended, configure its attributes (destroying the thread on failure), then resume (start) the thread.

> +
> +	if (thread_attr != NULL) {
> +		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
> +			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
> +			if (ret != 0) {
> +				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
> +				goto cleanup;
> +			}
> +
> +			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
> +				ret = rte_thread_translate_win32_error();
> +				RTE_LOG_WIN32_ERR("SetThreadGroupAffinity()");
> +				goto cleanup;
> +			}
> +		}
> +		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
> +		if (ret != 0) {
> +			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
> +			goto cleanup;
> +		}
> +	}
> +
> +	return 0;
> +
> +cleanup:
> +	if (thread_handle != NULL) {
> +		CloseHandle(thread_handle);
> +		thread_handle = NULL;
> +	}
> +	return ret;
> +}

[...]
> +
> +int
> +rte_thread_cancel(rte_thread_t thread_id) {
> +	int ret = 0;
> +	HANDLE thread_handle = NULL;
> +
> +	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id);
> +	if (thread_handle == NULL) {
> +		ret = rte_thread_translate_win32_error();
> +		RTE_LOG_WIN32_ERR("OpenThread()");
> +		goto cleanup;
> +	}
> +
> +	/*
> +	 * TODO: Behavior is different between POSIX and Windows threads.
> +	 * POSIX threads wait for a cancellation point.
> +	 * Current Windows emulation kills thread at any point.
> +	 */
> +	ret = TerminateThread(thread_handle, 0);

This is not acceptable.
There is a handful of pthread_cancel() usages in DPDK.
The threads they cancel take spinlocks and mutexes, so interrupt at arbitrary point may cause a deadlock.

User		Cancellation points	Notes
----		-------------------	-----
net/ipn3ke	libfdt functions?
net/kni		usleep			Linux-only
raw/ifpga	open/read/write/close
vdpa/ifc	read
vdpa/mlx5	usleep, nanosleep
lib/eventdev	rte_epoll_wait		no pthread CP

Possible solutions:

1. Make specific DPDK functions cancellation points for this API and ensure DPDK users of pthread_cancel() call it.  This way is almost non-invasive, but it's more work in EAL.

2. Divert from pthread style: add cancellation token concept, so that DPDK users can check themselves if they're cancelled. This is invasive, but very explicit and flexible.

> +	if (ret != 0) {
> +		ret = rte_thread_translate_win32_error();
> +		RTE_LOG_WIN32_ERR("TerminateThread()");
> +		goto cleanup;
> +	}
> +
> +cleanup:
> +	if (thread_handle != NULL) {
> +		CloseHandle(thread_handle);
> +		thread_handle = NULL;

This line is not needed.

> +	}
> +	return ret;
> +}
> +
>  int
>  rte_thread_key_create(rte_thread_key *key,
>  		__rte_unused void (*destructor)(void *))



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-04-29  0:50                     ` Dmitry Kozlyuk
@ 2021-04-30  2:39                       ` Narcisa Ana Maria Vasile
  2021-04-30 23:05                         ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-30  2:39 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Thu, Apr 29, 2021 at 03:50:38AM +0300, Dmitry Kozlyuk wrote:
> 2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Add function to translate Windows error codes to
> > errno-style error codes.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> 
> Commit topic should be "eal/windows", not "windows/eal".
> 
> > ---
> >  lib/librte_eal/include/rte_thread.h |  5 +-
> >  lib/librte_eal/windows/rte_thread.c | 75 ++++++++++++++++++++++-------
> >  2 files changed, 60 insertions(+), 20 deletions(-)
> > 
> > diff --git a/lib/librte_eal/include/rte_thread.h b/lib/librte_eal/include/rte_thread.h
> > index bfdd8e1b1..2d7b3bc05 100644
> 
> > @@ -87,15 +132,13 @@ rte_thread_key_create(rte_thread_key *key,
> >  	*key = malloc(sizeof(**key));
> >  	if ((*key) == NULL) {
> >  		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
> > -		rte_errno = ENOMEM;
> > -		return -1;
> > +		return ENOMEM;
> >  	}
> >  	(*key)->thread_index = TlsAlloc();
> >  	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
> >  		RTE_LOG_WIN32_ERR("TlsAlloc()");
> >  		free(*key);
> > -		rte_errno = ENOEXEC;
> > -		return -1;
> > +		return rte_thread_translate_win32_error();
> 
> Logging above can overwrite GetLastError() value.
> I suggest splitting rte_thread_translate_win32_error() into translation part
> for cases when you have error number already, and a wrapper that calls
> GetLastError() to shorten calling code.
> 

  Thanks Dmitry! I can split the translation function into something like:
  static int rte_thread_translate_win32_error(DWORD error) {
	switch(error) {
	    [...]
	}
  } 

  static int get_error_and_translate(void) {
     return rte_thread_translate_win32_error(GetLastError());
  }

  Is the above what you meant?

  Here, however, I don't think the wrapper over GetLastError() will be of much help, as 
  we still need to do something like:
  if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
       ret = GetLastError();
       RTE_LOG(DEBUG, EAL, "TlsAlloc() failed, GetLastError()=%lu: ", ret);
       free(*key);
       return rte_thread_translate_win32_error(ret);
  }

> Same applies below in this file.
> 
> [...]

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions
  2021-04-29 16:28                           ` Dmitry Kozlyuk
@ 2021-04-30  6:37                             ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-04-30  6:37 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Kinsella, Ray, Thomas Monjalon, dev, khot, navasile, dmitrym,
	roretzla, talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Thu, Apr 29, 2021 at 07:28:26PM +0300, Dmitry Kozlyuk wrote:
> 2021-04-29 13:05 (UTC+0100), Kinsella, Ray:
> > On 29/04/2021 08:44, Thomas Monjalon wrote:
> > > 29/04/2021 02:50, Dmitry Kozlyuk:  
> > >> 2021-04-02 18:38 (UTC-0700), Narcisa Ana Maria Vasile:  
> > >>> --- /dev/null
> > >>> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> > >>> @@ -0,0 +1,12 @@
> > >>> +/* SPDX-License-Identifier: BSD-3-Clause
> > >>> + * Copyright(c) 2021 Microsoft Corporation
> > >>> + */
> > >>> +
> > >>> +#ifndef _RTE_THREAD_TYPES_H_
> > >>> +#define _RTE_THREAD_TYPES_H_
> > >>> +
> > >>> +#include <rte_windows.h>
> > >>> +
> > >>> +typedef DWORD                       rte_thread_t;
> > >>> +
> > >>> +#endif /* _RTE_THREAD_TYPES_H_ */  
> > >>
> > >> pthread_t type in pthreads-win32 and winpthread is not 32 bit.
> > >> DPDK will have different ABI depending on a threading backend used.
> > >> Apps must know it at build time then. How do they discover it?
> > >> This is worth a warning in commit log and docs.  
> > > 
> > > Not sure this is an acceptable behaviour.
> > > In my opinion, ABI should not vary.
> > > +Cc Ray
> > >   
> > 
> > So pthread_t on Win32 should just map to the HANDLE datatype.
> > Which if memory serves is in fact a DWORD on Win32.
> 
> DWORD = uint32_t, HANDLE = void*, which are of different size on x64.
> I suggest an opaque 64-bit value to fit pthread_t from MinGW's winpthread.
> Only pthreads-win32 has a bigger pthread_t, but we don't have to support it.
> 
> > So I suspect that pthreads indirection is probably be just providing a circuitous route to end up in the same place, a HANDLE
> > 
> > IMHO
> > To absolutely guarantee no ABI change, we ought to be passing back void * not rte_thread_t. 
> 
> Yes. Only I'd use a type-safe version:
> 
> 	typedef struct rte_thread_tag {
> 		void *opaque; /* or uintptr_t per Tyler's suggestion */
> 	} rte_thread_t;

I agree we need a big enough value to fit different identifiers.
However, just to clarify, on Windows, there are two distinct thread-related identifiers:
thread id (DWORD) and thread HANDLE (void*).
In this API implementation I've used the rte_thread_t as the DWORD thread identifier, as the HANDLE
can be obtain from this DWORD using the OpenThread() function.
I will implement an opaque value that will be assigned the thread id (not the HANDLE) in this API.  


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v6 06/10] eal: add thread lifetime management
  2021-04-29 21:31                       ` [dpdk-dev] [EXTERNAL] " Dmitry Malloy
@ 2021-04-30 17:22                         ` Dmitry Kozlyuk
  2021-04-30 17:51                           ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-30 17:22 UTC (permalink / raw)
  To: Dmitry Malloy
  Cc: Narcisa Ana Maria Vasile, dev, thomas, Khoa To,
	Narcisa Ana Maria Vasile, Tyler Retzlaff, talshn, Omar Cardona,
	bruce.richardson, david.marchand, Kadam, Pallavi

2021-04-29 21:31 (UTC+0000), Dmitry Malloy:
> Thread cancellation is a pain point. Emulating it properly is nearly
> impossible (without hooking into various OS calls which are supposed to be
> "cancellation points"). I do like the cancellation token idea, but I'm not
> sure how existing clients, who rely on existing phtread_cancel() semantic,
> will react to that - it will require a code re-write. 
>
> How about we defer fixing this to another follow-up change?

I'm strictly against accepting code with known severe bugs.

Alternative:

1. Don't add rte_thread_cancel() in public API.
2. Implement rte_thread_cancel() as internal API with cancellation tokens.
3. Rewrite DPDK code to use rte_thread_cancel().
4. For external users:
4.1. If their app is using pthread, they can use pthread backend for DPDK and
call pthread_cancel() directly.
4.2. If their app is not designed for pthread, they probably don't need
pthread_cancel() semantics and cancel threads another way.
4.3. If it's a brand new app, they will only use public API.

In 4.1 users need a pthread_t. In principle, they can call pthread_self()
from the thread to be cancelled and pass it to the thread that cancels. Or we
could provide API to get backend type and native handle. Since users have to
rewrite their code anyway to move from pthread to rte_thread, I'm for the
former approach. "Escape hatch" API would be very fragile.

P.S. Please avoid top-posting.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 07/10] eal: implement functions for mutex management
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-04-30 17:47                     ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-30 17:47 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
> index a884daf17..37bc7af2b 100644
> --- a/lib/librte_eal/include/rte_thread_types.h
> +++ b/lib/librte_eal/include/rte_thread_types.h
> @@ -7,9 +7,12 @@
>  
>  #include <pthread.h>
>  
> +#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
> +

I'd wrap this in #ifndef RTE_EXEC_ENV_WINDOWS,
so that portable code couldn't accidentally rely on it.

>  #define EAL_THREAD_PRIORITY_NORMAL               0
>  #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
>  
>  typedef pthread_t                       rte_thread_t;
> +typedef pthread_mutex_t                 rte_thread_mutex_t;
>  
>  #endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> index 8cb4b3856..47c6b2664 100644
> --- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> @@ -11,5 +11,6 @@
>  #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
>  
>  typedef DWORD                       rte_thread_t;
> +typedef CRITICAL_SECTION            rte_thread_mutex_t;
>  
>  #endif /* _RTE_THREAD_TYPES_H_ */

You have to ensure that sizeof(rte_thread_mutex_t) is the same with both
backends. MinGW's winpthread has "typedef void *pthread_mutex_t", while
CRITICAL_SECTION is much larger.

If you decide to make rte_thread_mutext_t a pointer on Windows,
consider implementing RTE_THREAD_MUTEX_INITILIZER.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v6 06/10] eal: add thread lifetime management
  2021-04-30 17:22                         ` Dmitry Kozlyuk
@ 2021-04-30 17:51                           ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-30 17:51 UTC (permalink / raw)
  To: Dmitry Malloy
  Cc: Narcisa Ana Maria Vasile, dev, thomas, Khoa To,
	Narcisa Ana Maria Vasile, Tyler Retzlaff, talshn, Omar Cardona,
	bruce.richardson, david.marchand, Kadam, Pallavi

2021-04-30 20:22 (UTC+0300), Dmitry Kozlyuk:
> 2021-04-29 21:31 (UTC+0000), Dmitry Malloy:
> > [...]
> > How about we defer fixing this to another follow-up change?  
> 
> I'm strictly against accepting code with known severe bugs.
> 
> Alternative:
> 
> 1. Don't add rte_thread_cancel() in public API.
> 2. Implement rte_thread_cancel() as internal API with cancellation tokens.
> 3. Rewrite DPDK code to use rte_thread_cancel().
> [...]

Or just don't export this function on Windows for now.
None of the drivers using it is soon to be enabled for Windows,
and portable apps don't need it anyway.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 08/10] eal: implement functions for thread barrier management
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-04-30 18:06                     ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-30 18:06 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
> [...]
> diff --git a/lib/librte_eal/include/rte_thread_types.h b/lib/librte_eal/include/rte_thread_types.h
> index 37bc7af2b..b055bbf67 100644
> --- a/lib/librte_eal/include/rte_thread_types.h
> +++ b/lib/librte_eal/include/rte_thread_types.h
> @@ -7,6 +7,7 @@
>  
>  #include <pthread.h>
>  
> +#define RTE_THREAD_BARRIER_SERIAL_THREAD PTHREAD_BARRIER_SERIAL_THREAD
>  #define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
>  
>  #define EAL_THREAD_PRIORITY_NORMAL               0
> @@ -14,5 +15,6 @@
>  
>  typedef pthread_t                       rte_thread_t;
>  typedef pthread_mutex_t                 rte_thread_mutex_t;
> +typedef pthread_barrier_t               rte_thread_barrier_t;
>  
>  #endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/librte_eal/windows/include/rte_windows_thread_types.h b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> index 47c6b2664..b6209e6eb 100644
> --- a/lib/librte_eal/windows/include/rte_windows_thread_types.h
> +++ b/lib/librte_eal/windows/include/rte_windows_thread_types.h
> @@ -7,10 +7,13 @@
>  
>  #include <rte_windows.h>
>  
> +#define RTE_THREAD_BARRIER_SERIAL_THREAD TRUE
> +
>  #define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
>  #define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
>  
>  typedef DWORD                       rte_thread_t;
>  typedef CRITICAL_SECTION            rte_thread_mutex_t;
> +typedef SYNCHRONIZATION_BARRIER     rte_thread_barrier_t;
>  
>  #endif /* _RTE_THREAD_TYPES_H_ */

Please ensure that for both backends
sizeof(rte_thread_barrier_t) is the same
and RTE_THREAD_BARRIER_SERIAL_THREAD has same value.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v6 02/10] eal: add thread attributes
  2021-04-29 15:52                         ` [dpdk-dev] [EXTERNAL] " Tyler Retzlaff
@ 2021-04-30 23:00                           ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-30 23:00 UTC (permalink / raw)
  To: Tyler Retzlaff
  Cc: thomas, Narcisa Ana Maria Vasile, dev, Khoa To,
	Narcisa Ana Maria Vasile, Dmitry Malloy, talshn, Omar Cardona,
	bruce.richardson, david.marchand, Kadam, Pallavi

2021-04-29 15:52 (UTC+0000), Tyler Retzlaff:
> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net> 
> Sent: Thursday, April 29, 2021 12:48 AM
> 
> 
> 29/04/2021 02:50, Dmitry Kozlyuk:
> > > 2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:  
> > > > +int
> > > > +rte_thread_attr_init(rte_thread_attr_t *attr) {
> > > > +	if (attr == NULL) {
> > > > +		RTE_LOG(DEBUG, EAL,
> > > > +		"Unable to init thread attributes, invalid parameter\n");
> > > > +		return EINVAL;
> > > > +	}  
> > > 
> > > This message doesn't add value for debugging: caller already knows 
> > > that attribute initialization failed (that's what function attempts to 
> > > do) and that the parameter is invalid (EINVAL).
> > > I'd remove it (same applies below).
> > > If you find it useful to keep, an extra indent missing (also more below).  
> 
> > Recently in ethdev we added more messages like this for NULL parameters.
> > I agree it is not a lot useful but I understand that lazy developers may like it ;)  
> 
> Shouldn't this specific case be an assert?  Unless we are trying to maintain compatibility with existing badly designed semantics.
>
> The whole calling pattern is non-sensible, the caller passes an NULL parameter to a function where the input contract is non-NULL and then proceeds to handle the error by doing what that could possibly be useful exactly?

+1 in this case.
This function is only specified to diagnose ENOMEM. On my Linux machine
pthread_attr_init(NULL) crashes, I guess that would be compatible behavior.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors
  2021-04-30  2:39                       ` Narcisa Ana Maria Vasile
@ 2021-04-30 23:05                         ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-30 23:05 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-29 19:39 (UTC-0700), Narcisa Ana Maria Vasile:
> On Thu, Apr 29, 2021 at 03:50:38AM +0300, Dmitry Kozlyuk wrote:
> > 2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:  
> > > From: Narcisa Vasile <navasile@microsoft.com>
[...]
> > >  	(*key)->thread_index = TlsAlloc();
> > >  	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
> > >  		RTE_LOG_WIN32_ERR("TlsAlloc()");
> > >  		free(*key);
> > > -		rte_errno = ENOEXEC;
> > > -		return -1;
> > > +		return rte_thread_translate_win32_error();  
> > 
> > Logging above can overwrite GetLastError() value.
> > I suggest splitting rte_thread_translate_win32_error() into translation part
> > for cases when you have error number already, and a wrapper that calls
> > GetLastError() to shorten calling code.
> >   
> 
>   Thanks Dmitry! I can split the translation function into something like:
>   static int rte_thread_translate_win32_error(DWORD error) {
> 	switch(error) {
> 	    [...]
> 	}
>   } 
> 
>   static int get_error_and_translate(void) {
>      return rte_thread_translate_win32_error(GetLastError());
>   }
> 
>   Is the above what you meant?
> 
>   Here, however, I don't think the wrapper over GetLastError() will be of much help, as 
>   we still need to do something like:
>   if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
>        ret = GetLastError();
>        RTE_LOG(DEBUG, EAL, "TlsAlloc() failed, GetLastError()=%lu: ", ret);
>        free(*key);
>        return rte_thread_translate_win32_error(ret);
>   }

I'm afraid we don't have a choice, the logs with exact Win32 API call and its
result is very handy for debugging. Patches 4/10 and 5/10 shorten it a bit.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v6 04/10] eal: implement functions for thread affinity management
  2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-05-02  0:41                     ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-05-02  0:41 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-04-02 18:39 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> +/**
> + * Get the affinity of thread 'thread_id' and store it
> + * in 'cpuset'.
> + *
> + * @param thread_id
> + *    Id of the thread for which to get the affinity.
> + *
> + * @param cpuset_size
> + *    Size of the cpu set.
> + *
> + * @param cpuset
> + *   Pointer for storing the affinity value.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.
> + */
> +__rte_experimental
> +int rte_thread_get_affinity_by_id(rte_thread_t thread_id, size_t cpuset_size,
> +				  rte_cpuset_t *cpuset);

Existing DPDK functions with `rte_cpuset_t` don't take `cpuset_size`.
Is it really necessary here?

>  /**
>   * Initialize the attributes of a thread.
>   * These attributes can be passed to the rte_thread_create() function
> diff --git a/lib/librte_eal/windows/eal_lcore.c b/lib/librte_eal/windows/eal_lcore.c
> index a85149be9..023c5c895 100644
> --- a/lib/librte_eal/windows/eal_lcore.c
> +++ b/lib/librte_eal/windows/eal_lcore.c
[...]
> +
> +static bool
> +eal_check_for_duplicate_numa(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)

This function's purpose is not to check for "duplicate NUMA" (what's this?).
Please find an eloquent name. The comment below just explained a case when a
NUMA node may be reported as two logical processors due to processor group
size limitiation.

> +{
> +	const unsigned int node_id = info->NumaNode.NodeNumber;
> +	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
> +	struct lcore_map *lcore;
> +	unsigned int socket_id;
> +
> +	/* NUMA node may be reported multiple times if it includes
> +	 * cores from different processor groups, e. g. 80 cores
> +	 * of a physical processor comprise one NUMA node, but two
> +	 * processor groups, because group size is limited by 32/64.
> +	 */
> +	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
> +		if (cpu_map.sockets[socket_id].node_id == node_id)
> +			break;
> +	}
> +
> +	if (socket_id == cpu_map.socket_count) {
> +		if (socket_id == RTE_DIM(cpu_map.sockets))
> +			return true;
> +
> +		cpu_map.sockets[socket_id].node_id = node_id;
> +		cpu_map.socket_count++;
> +	}
> +
> +	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
> +		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
> +			continue;
> +
> +		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
> +			return true;
> +
> +		lcore = &cpu_map.lcores[cpu_map.lcore_count];
> +		lcore->socket_id = socket_id;
> +		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
> +		cpu_map.lcore_count++;
> +	}
> +	return false;
> +}
> +
>  int
>  eal_create_cpu_map(void)
>  {
[...]
> +		if (eal_check_for_duplicate_numa(info))
> +			break;

Assignments to "full" are lost, so if we run out of space to store info,
users won't get a warning message.

>  
>  		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
>  			(uint8_t *)info + info->Size);
>  	}
>  
> +	if (eal_query_group_affinity()) {
> +		/*
> +		 * No need to set rte_errno here.
> +		 * It is set by eal_query_group_affinity().
> +		 */
> +		ret = -1;
> +		goto exit;
> +	}
>  exit:
>  	if (full) {
>  		/* Not a fatal error, but important for troubleshooting. */
> @@ -139,7 +208,7 @@ eal_create_cpu_map(void)
>  
>  	free(infos);
>  
> -	return 0;
> +	return ret;
>  }
>  
>  int
> @@ -165,3 +234,12 @@ eal_socket_numa_node(unsigned int socket_id)
>  {
>  	return cpu_map.sockets[socket_id].node_id;
>  }
> +
> +PGROUP_AFFINITY
> +eal_get_cpu_affinity(size_t cpu_index)
> +{
> +	if (cpu_index < CPU_SETSIZE)
> +		return &cpu_map.cpus[cpu_index];
> +
> +	return NULL;
> +}
> diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
> index 478accc1b..dc5dc8240 100644
> --- a/lib/librte_eal/windows/eal_windows.h
> +++ b/lib/librte_eal/windows/eal_windows.h
> @@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
>   */
>  unsigned int eal_socket_numa_node(unsigned int socket_id);
>  
> +/**
> + * Get pointer to the group affinity for the cpu.
> + *
> + * @param cpu_index
> + *  Index of the cpu, as it comes from rte_cpuset_t.
> + * @return
> + *  Pointer to the group affinity for the cpu.
> + */
> +PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);

NULL can be returned. Actually, it's a private API always used in a way that
cannot trigger error, so probably can be replaced with an assert.

> +
>  /**
>   * Schedule code for execution in the interrupt thread.
>   *
> diff --git a/lib/librte_eal/windows/rte_thread.c b/lib/librte_eal/windows/rte_thread.c
> index ecd2f810f..2fa130b1f 100644
> --- a/lib/librte_eal/windows/rte_thread.c
> +++ b/lib/librte_eal/windows/rte_thread.c
> @@ -4,9 +4,9 @@
>   */
>  
>  #include <rte_common.h>
> -#include <rte_errno.h>
>  #include <rte_thread.h>
> -#include <rte_windows.h>
> +
> +#include "eal_windows.h"
>  
>  struct eal_tls_key {
>  	DWORD thread_index;
> @@ -69,6 +69,134 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
>  	return t1 == t2 ? 1 : 0;
>  }
>  
> +static int
> +rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
> +			       PGROUP_AFFINITY affinity)
> +{
> +	int ret = 0;
> +	PGROUP_AFFINITY cpu_affinity = NULL;
> +
> +	memset(affinity, 0, sizeof(GROUP_AFFINITY));
> +	affinity->Group = (USHORT)-1;
> +
> +	/* Check that all cpus of the set belong to the same processor group and
> +	 * accumulate thread affinity to be applied.
> +	 */
> +	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
> +		if (!CPU_ISSET(cpu_idx, cpuset))
> +			continue;
> +
> +		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
> +
> +		if (affinity->Group == (USHORT)-1) {
> +			affinity->Group = cpu_affinity->Group;
> +		} else if (affinity->Group != cpu_affinity->Group) {

Just to be clear: is it a kernel limitation that a thread can only run on
cores of one processor group, or do we impose it so that API is atomic
(transactional), i.e. because one of multiple SetThreadGroupAffinity() calls
may fail and leave thread partially affinitized?

> +			ret = EINVAL;
> +			goto cleanup;
> +		}
> +
> +		affinity->Mask |= cpu_affinity->Mask;
> +	}
> +
> +	if (affinity->Mask == 0) {
> +		ret = EINVAL;
> +		goto cleanup;
> +	}
> +
> +cleanup:

This label and `goto`s above are not needed.

> +	return ret;
> +}
> +
> +int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
> +			    size_t cpuset_size,
> +			    const rte_cpuset_t *cpuset)
> +{

Return type should be on a separate line here and in Unix file, too.

[...]

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 00/10] eal: Add EAL API for threading
  2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
                                     ` (10 preceding siblings ...)
  2021-04-12  7:56                   ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading David Marchand
@ 2021-06-01 20:55                   ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                                       ` (10 more replies)
  11 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   8 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   5 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/dpaa/dpaa_bus.c                   |  14 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  19 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   4 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   2 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  26 +-
 drivers/net/axgbe/axgbe_common.h              |   2 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   8 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  24 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   6 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  46 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  73 +-
 examples/kni/main.c                           |   6 +-
 .../performance-thread/pthread_shim/main.c    |   2 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  12 +-
 lib/eal/common/eal_common_options.c           |  34 +-
 lib/eal/common/eal_common_proc.c              |  48 +-
 lib/eal/common/eal_common_thread.c            |  31 +-
 lib/eal/common/eal_common_trace.c             |   2 +-
 lib/eal/common/eal_internal_cfg.h             |   2 +
 lib/eal/common/eal_options.h                  |   2 +
 lib/eal/common/eal_private.h                  |   2 +-
 lib/eal/common/malloc_mp.c                    |  32 +-
 lib/eal/common/meson.build                    |   1 +
 lib/eal/common/rte_thread.c                   | 416 +++++++++++
 lib/eal/freebsd/eal.c                         |  40 +-
 lib/eal/freebsd/eal_alarm.c                   |  12 +-
 lib/eal/freebsd/eal_interrupts.c              |   4 +-
 lib/eal/freebsd/eal_thread.c                  |  14 +-
 lib/eal/include/meson.build                   |   1 +
 lib/eal/include/rte_lcore.h                   |   8 +-
 lib/eal/include/rte_per_lcore.h               |   2 -
 lib/eal/include/rte_thread.h                  | 364 +++++++++-
 lib/eal/include/rte_thread_types.h            |  14 +
 lib/eal/linux/eal.c                           |  43 +-
 lib/eal/linux/eal_alarm.c                     |  10 +-
 lib/eal/linux/eal_interrupts.c                |   4 +-
 lib/eal/linux/eal_thread.c                    |  18 +-
 lib/eal/linux/eal_timer.c                     |   2 +-
 lib/eal/unix/meson.build                      |   1 -
 lib/eal/unix/rte_thread.c                     |  92 ---
 lib/eal/version.map                           |  21 +
 lib/eal/windows/eal.c                         |  40 +-
 lib/eal/windows/eal_interrupts.c              |  10 +-
 lib/eal/windows/eal_lcore.c                   | 169 +++--
 lib/eal/windows/eal_thread.c                  |  28 +-
 lib/eal/windows/eal_windows.h                 |  20 +-
 lib/eal/windows/include/meson.build           |   1 +
 lib/eal/windows/include/pthread.h             | 186 -----
 .../include/rte_windows_thread_types.h        |  19 +
 lib/eal/windows/include/sched.h               |   2 +-
 lib/eal/windows/meson.build                   |   7 +-
 lib/eal/windows/rte_thread.c                  | 671 +++++++++++++++++-
 lib/ethdev/rte_ethdev.c                       |   4 +-
 lib/ethdev/rte_ethdev_core.h                  |   5 +-
 lib/ethdev/rte_flow.c                         |   4 +-
 lib/eventdev/rte_event_eth_rx_adapter.c       |   6 +-
 lib/vhost/fd_man.c                            |  40 +-
 lib/vhost/fd_man.h                            |   6 +-
 lib/vhost/socket.c                            | 130 ++--
 lib/vhost/vhost.c                             |  10 +-
 meson_options.txt                             |   2 +
 105 files changed, 2298 insertions(+), 972 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 create mode 100644 lib/eal/include/rte_thread_types.h
 delete mode 100644 lib/eal/unix/rte_thread.c
 delete mode 100644 lib/eal/windows/include/pthread.h
 create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 01/10] eal: add thread id and simple thread functions
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.
---
 lib/eal/common/rte_thread.c                   | 105 ++++++++++++++++++
 lib/eal/include/rte_thread.h                  |  53 +++++++--
 lib/eal/include/rte_thread_types.h            |  10 ++
 .../include/rte_windows_thread_types.h        |  10 ++
 lib/eal/windows/rte_thread.c                  |  17 +++
 5 files changed, 186 insertions(+), 9 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 create mode 100644 lib/eal/include/rte_thread_types.h
 create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
new file mode 100644
index 0000000000..1292f7a8f8
--- /dev/null
+++ b/lib/eal/common/rte_thread.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id = { 0 };
+
+	thread_id.opaque_id = pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1.opaque_id, t2.opaque_id);
+}
+
+int
+rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_thread_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_key_delete(rte_thread_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_value_set(rte_thread_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_value_get(rte_thread_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..347df1a6ae 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,50 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +104,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +119,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +134,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
new file mode 100644
index 0000000000..d67b24a563
--- /dev/null
+++ b/lib/eal/include/rte_thread_types.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 0000000000..60e6d94553
--- /dev/null
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..3f3ebba21f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id = { 0 };
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 02/10] eal: add thread attributes
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the already known “rte_cpuset_t” type.

An rte_thread_attr_t object can be set to the default values
by calling *rte_thread_attr_init()*.
---
 lib/eal/common/rte_thread.c                   | 51 +++++++++++
 lib/eal/include/rte_thread.h                  | 89 +++++++++++++++++++
 lib/eal/include/rte_thread_types.h            |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/eal/windows/rte_thread.c                  | 53 +++++++++++
 5 files changed, 199 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 1292f7a8f8..4b1e8f995e 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,56 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1.opaque_id, t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_ASSERT(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 347df1a6ae..eff00023d7 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -36,6 +36,26 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -66,6 +86,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index d67b24a563..996232c636 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,4 +7,7 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 60e6d94553..5bdeaad3d4 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,4 +7,7 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 3f3ebba21f..cc319d3628 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -5,6 +5,7 @@
 
 #include <rte_common.h>
 #include <rte_errno.h>
+#include <rte_debug.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
 
@@ -28,6 +29,58 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_ASSERT(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 03/10] eal/windows: translate Windows errors to errno-style errors
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.
---
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 90 +++++++++++++++++++++++++++---------
 2 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index eff00023d7..f3eeb28753 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -236,9 +236,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index cc319d3628..6ea1dc2a05 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char* message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -85,18 +133,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -104,16 +152,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -122,19 +170,17 @@ rte_thread_key_delete(rte_thread_key key)
 int
 rte_thread_value_set(rte_thread_key key, const void *value)
 {
+	int ret;
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -143,16 +189,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 04/10] eal: implement functions for thread affinity management
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (2 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.
---
 lib/eal/common/rte_thread.c   |  14 +++
 lib/eal/include/rte_thread.h  |  36 ++++++++
 lib/eal/windows/eal_lcore.c   | 169 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 127 ++++++++++++++++++++++++-
 5 files changed, 310 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 4b1e8f995e..ceb27feaa7 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,20 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1.opaque_id, t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index f3eeb28753..1f02962146 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -86,6 +86,42 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..519a62b96d 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +177,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +209,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +235,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 478accc1b9..dc5dc8240a 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 6ea1dc2a05..9e74a538c2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_errno.h>
 #include <rte_debug.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,130 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 05/10] eal: implement thread priority management functions
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (3 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                       ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL
---
 lib/eal/common/rte_thread.c                   | 51 ++++++++++
 lib/eal/include/rte_thread.h                  | 17 ++++
 lib/eal/include/rte_thread_types.h            |  3 -
 .../include/rte_windows_thread_types.h        |  3 -
 lib/eal/windows/rte_thread.c                  | 92 +++++++++++++++++++
 5 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ceb27feaa7..5cee19bb7d 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -48,6 +48,57 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri, int *pol)
+{
+	RTE_VERIFY(os_pri != NULL);
+	RTE_VERIFY(pol != NULL);
+
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri)
+	{
+		case RTE_THREAD_PRIORITY_NORMAL:
+			*pol = SCHED_OTHER;
+
+			/*
+			 * Choose the middle of the range to represent
+			 * the priority 'normal'.
+			 * On Linux, this should be 0, since both
+			 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+			 */
+			*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2;
+			break;
+		case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+			*pol = SCHED_RR;
+			*os_pri = sched_get_priority_max(SCHED_RR);
+			break;
+		default:
+			RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+			return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority, &policy);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return pthread_setschedparam(thread_id.opaque_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 1f02962146..5c54cd9d67 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -122,6 +122,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index 996232c636..d67b24a563 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,7 +7,4 @@
 
 #include <pthread.h>
 
-#define EAL_THREAD_PRIORITY_NORMAL               0
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
-
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 5bdeaad3d4..60e6d94553 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,7 +7,4 @@
 
 #include <rte_windows.h>
 
-#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
-
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 9e74a538c2..6dc3d575c0 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -202,6 +202,98 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	RTE_VERIFY(os_pri != NULL);
+	RTE_VERIFY(pri_class != NULL);
+
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri)
+	{
+		case RTE_THREAD_PRIORITY_NORMAL:
+			*pri_class = NORMAL_PRIORITY_CLASS;
+			*os_pri = THREAD_PRIORITY_NORMAL;
+			break;
+		case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+			*pri_class = REALTIME_PRIORITY_CLASS;
+			*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+			break;
+		default:
+			RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+			return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	int priority_class = NORMAL_PRIORITY_CLASS;
+	int os_priority = THREAD_PRIORITY_NORMAL;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority, &priority_class);
+	if (ret != 0) {
+		return ret;
+	}
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = thread_log_last_error("OpenProcess()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 06/10] eal: add thread lifetime management
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (4 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                       ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling.

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.
---
 lib/eal/common/rte_thread.c  | 110 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  53 ++++++++++++
 lib/eal/windows/rte_thread.c | 155 +++++++++++++++++++++++++++++++++++
 3 files changed, 318 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 5cee19bb7d..2e06f16a69 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -149,6 +149,116 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(&thread_id->opaque_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5c54cd9d67..2ff207f8bb 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -208,6 +208,59 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 		enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 6dc3d575c0..321b44caf6 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	void* (*start_routine) (void*);
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -346,6 +351,156 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	intptr_t func_ret = 0;
+	struct thread_routine_ctx ctx = { NULL, NULL };
+
+	ctx.start_routine = pctx->start_routine;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (intptr_t)ctx.start_routine(ctx.routine_args);
+	return (DWORD)func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	DWORD tid = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->start_routine = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = thread_log_last_error("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 07/10] eal: implement functions for mutex management
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (5 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

On Linux, static initialization of a mutex is possible
through PTHREAD_MUTEX_INITIALIZER.

Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

To simulate static initialization, a fake initializator has been added:
The rte_mutex_lock() function will verify if the mutex has been initialized
using this fake initializer and if so, it will perform additional
initialization.
---
 lib/eal/common/rte_thread.c                   | 24 ++++++
 lib/eal/include/rte_thread.h                  | 53 ++++++++++++
 lib/eal/include/rte_thread_types.h            |  4 +
 .../include/rte_windows_thread_types.h        |  9 ++
 lib/eal/windows/rte_thread.c                  | 83 ++++++++++++++++++-
 5 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 2e06f16a69..e8e4af0451 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -249,6 +249,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 2ff207f8bb..2fca662616 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -248,6 +248,58 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
@@ -269,6 +321,7 @@ int rte_thread_cancel(rte_thread_t thread_id);
  *
  * @param cpusetp
  *   Pointer to CPU affinity to set.
+ *
  * @return
  *   On success, return 0; otherwise return -1;
  */
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index d67b24a563..7bb0d2948c 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,4 +7,8 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
+typedef pthread_mutex_t                 rte_thread_mutex_t;
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 60e6d94553..c6c8502bfb 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,4 +7,13 @@
 
 #include <rte_windows.h>
 
+#define WINDOWS_MUTEX_INITIALIZER               (void*)-1
+#define RTE_THREAD_MUTEX_INITIALIZER            {WINDOWS_MUTEX_INITIALIZER}
+
+struct thread_mutex_t {
+	void* mutex_id;
+};
+
+typedef struct thread_mutex_t rte_thread_mutex_t;
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 321b44caf6..f81876f4f2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -470,6 +470,88 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	int ret = 0;
+	void* id = 0;
+	rte_thread_mutex_t m;
+
+	RTE_VERIFY(mutex != NULL);
+
+	/* Check if mutex has been statically initialized */
+	id = InterlockedCompareExchangePointer(&mutex->mutex_id, mutex->mutex_id, WINDOWS_MUTEX_INITIALIZER);
+	/* If mutex has been statically initialized */
+	if (id == WINDOWS_MUTEX_INITIALIZER) {
+		ret = rte_thread_mutex_init(&m);
+		if (ret != 0) {
+			return ret;
+		}
+
+		id = InterlockedCompareExchangePointer(&mutex->mutex_id, m.mutex_id, WINDOWS_MUTEX_INITIALIZER);
+		/* If meanwhile the mutex was initialized by a different thread,
+		 * destroy the local initialization.
+		 */
+		if (id != WINDOWS_MUTEX_INITIALIZER) {
+			rte_thread_mutex_destroy(&m);
+		}
+	}
+
+	EnterCriticalSection(mutex->mutex_id);
+
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (mutex->mutex_id == WINDOWS_MUTEX_INITIALIZER) {
+		goto cleanup;
+	}
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+
+cleanup:
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
@@ -542,7 +624,6 @@ rte_thread_key_delete(rte_thread_key key)
 int
 rte_thread_value_set(rte_thread_key key, const void *value)
 {
-	int ret;
 	char *p;
 
 	if (key == NULL) {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 08/10] eal: implement functions for thread barrier management
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (6 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                       ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e8e4af0451..7560585784 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -273,6 +273,67 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return ret;
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to destroy barrier, ret = %d\n", ret);
+	}
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 2fca662616..06b23571a1 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -29,6 +29,11 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
 /**
  * Thread id descriptor.
  */
@@ -56,6 +61,13 @@ typedef struct {
 	rte_cpuset_t cpuset; /**< thread affinity */
 } rte_thread_attr_t;
 
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void* barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -300,6 +312,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index f81876f4f2..e1778b603e 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -552,6 +552,62 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 09/10] eal: add EAL argument for setting thread priority
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (7 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index 66f9114715..773cefdff7 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1406,6 +1407,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1819,7 +1838,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2082,6 +2107,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (8 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-06-01 20:55                     ` Narcisa Ana Maria Vasile
  2021-06-02 15:50                       ` Tal Shnaiderman
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-01 20:55 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.
---
 app/test/process.h                            |   8 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   5 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/dpaa/dpaa_bus.c                   |  14 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  19 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   4 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   2 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  26 +--
 drivers/net/axgbe/axgbe_common.h              |   2 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |   8 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   4 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   8 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  24 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   6 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  46 ++---
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   6 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  73 +++----
 examples/kni/main.c                           |   6 +-
 .../performance-thread/pthread_shim/main.c    |   2 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  12 +-
 lib/eal/common/eal_common_options.c           |   6 +-
 lib/eal/common/eal_common_proc.c              |  48 ++---
 lib/eal/common/eal_common_thread.c            |  31 ++-
 lib/eal/common/eal_common_trace.c             |   2 +-
 lib/eal/common/eal_private.h                  |   2 +-
 lib/eal/common/malloc_mp.c                    |  32 +--
 lib/eal/common/meson.build                    |   1 +
 lib/eal/freebsd/eal.c                         |  40 +++-
 lib/eal/freebsd/eal_alarm.c                   |  12 +-
 lib/eal/freebsd/eal_interrupts.c              |   4 +-
 lib/eal/freebsd/eal_thread.c                  |  14 +-
 lib/eal/include/meson.build                   |   1 +
 lib/eal/include/rte_lcore.h                   |   8 +-
 lib/eal/include/rte_per_lcore.h               |   2 -
 lib/eal/linux/eal.c                           |  43 ++--
 lib/eal/linux/eal_alarm.c                     |  10 +-
 lib/eal/linux/eal_interrupts.c                |   4 +-
 lib/eal/linux/eal_thread.c                    |  18 +-
 lib/eal/linux/eal_timer.c                     |   2 +-
 lib/eal/unix/meson.build                      |   1 -
 lib/eal/unix/rte_thread.c                     |  92 ---------
 lib/eal/version.map                           |  21 ++
 lib/eal/windows/eal.c                         |  40 +++-
 lib/eal/windows/eal_interrupts.c              |  10 +-
 lib/eal/windows/eal_thread.c                  |  28 +--
 lib/eal/windows/eal_windows.h                 |  10 -
 lib/eal/windows/include/meson.build           |   1 +
 lib/eal/windows/include/pthread.h             | 186 ------------------
 lib/eal/windows/include/sched.h               |   2 +-
 lib/eal/windows/meson.build                   |   7 +-
 lib/ethdev/rte_ethdev.c                       |   4 +-
 lib/ethdev/rte_ethdev_core.h                  |   5 +-
 lib/ethdev/rte_flow.c                         |   4 +-
 lib/eventdev/rte_event_eth_rx_adapter.c       |   6 +-
 lib/vhost/fd_man.c                            |  40 ++--
 lib/vhost/fd_man.h                            |   6 +-
 lib/vhost/socket.c                            | 130 ++++++------
 lib/vhost/vhost.c                             |  10 +-
 meson_options.txt                             |   2 +
 97 files changed, 683 insertions(+), 892 deletions(-)
 delete mode 100644 lib/eal/unix/rte_thread.c
 delete mode 100644 lib/eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index a09a088477..9e4be17bad 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -26,7 +26,7 @@
 
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-#include <pthread.h>
+#include <rte_thread.h>
 extern void *send_pkts(void *empty);
 extern uint16_t flag_for_send_pkts;
 #endif
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 	int rc;
 #endif
 #endif
@@ -128,7 +128,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
-		rc = pthread_create(&thread, NULL, &send_pkts, NULL);
+		rc = rte_thread_create(&thread, NULL, &send_pkts, NULL);
 		if (rc != 0) {
 			rte_panic("Cannot start send pkts thread: %s\n",
 				  strerror(rc));
@@ -143,7 +143,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fce..c507e423e0 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a8..3d9663f5ee 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d064..ce79d9c17a 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 017bb2efbb..4070eb200d 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -262,6 +262,10 @@ else # for 32-bit we need smaller reserved memory areas
     dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da1..c66a0946ca 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,10 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a2..dc5f02bec1 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681cd..6d2d10cdf0 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 173041c026..baa1c7c6dc 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -10,7 +10,7 @@
 #include <limits.h>
 #include <sched.h>
 #include <signal.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
 #include <sys/eventfd.h>
@@ -48,7 +48,7 @@ static struct rte_dpaa_bus rte_dpaa_bus;
 struct netcfg_info *dpaa_netcfg;
 
 /* define a variable to hold the portal_key, once created.*/
-static pthread_key_t dpaa_portal_key;
+static rte_thread_key dpaa_portal_key;
 
 unsigned int dpaa_svr_family;
 
@@ -316,10 +316,10 @@ int rte_dpaa_portal_init(void *arg)
 	DPAA_PER_LCORE_PORTAL->bman_idx = bman_get_portal_index();
 	DPAA_PER_LCORE_PORTAL->tid = syscall(SYS_gettid);
 
-	ret = pthread_setspecific(dpaa_portal_key,
+	ret = rte_thread_value_set(dpaa_portal_key,
 				  (void *)DPAA_PER_LCORE_PORTAL);
 	if (ret) {
-		DPAA_BUS_LOG(ERR, "pthread_setspecific failed on core %u"
+		DPAA_BUS_LOG(ERR, "rte_thread_value_set failed on core %u"
 			     " (lcore=%u) with ret: %d", cpu, lcore, ret);
 		dpaa_portal_finish(NULL);
 
@@ -377,7 +377,7 @@ dpaa_portal_finish(void *arg)
 	bman_thread_finish();
 	qman_thread_finish();
 
-	pthread_setspecific(dpaa_portal_key, NULL);
+	rte_thread_value_set(dpaa_portal_key, NULL);
 
 	rte_free(dpaa_io_portal);
 	dpaa_io_portal = NULL;
@@ -453,9 +453,9 @@ rte_dpaa_bus_scan(void)
 	/* create the key, supplying a function that'll be invoked
 	 * when a portal affined thread will be deleted.
 	 */
-	ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
+	ret = rte_thread_key_create(&dpaa_portal_key, dpaa_portal_finish);
 	if (ret) {
-		DPAA_BUS_LOG(DEBUG, "Unable to create pthread key. (%d)", ret);
+		DPAA_BUS_LOG(DEBUG, "Unable to create thread key. (%d)", ret);
 		dpaa_clean_device_list();
 		return ret;
 	}
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1d..dffbdff666 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -13,7 +13,7 @@
 #include <stdarg.h>
 #include <inttypes.h>
 #include <signal.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <sys/ioctl.h>
@@ -59,7 +59,7 @@ uint8_t dpaa2_dqrr_size;
 uint8_t dpaa2_eqcr_size;
 
 /* Variable to hold the portal_key, once created.*/
-static pthread_key_t dpaa2_portal_key;
+static rte_thread_key dpaa2_portal_key;
 
 /*Stashing Macros default for LS208x*/
 static int dpaa2_core_cluster_base = 0x04;
@@ -92,10 +92,9 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
@@ -296,9 +295,9 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(void)
 		}
 	}
 
-	ret = pthread_setspecific(dpaa2_portal_key, (void *)dpio_dev);
+	ret = rte_thread_value_set(dpaa2_portal_key, (void *)dpio_dev);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_setspecific failed with ret: %d", ret);
+		DPAA2_BUS_ERR("rte_thread_value_set failed with ret: %d", ret);
 		dpaa2_put_qbman_swp(dpio_dev);
 		return NULL;
 	}
@@ -357,7 +356,7 @@ static void dpaa2_portal_finish(void *arg)
 	dpaa2_put_qbman_swp(RTE_PER_LCORE(_dpaa2_io).dpio_dev);
 	dpaa2_put_qbman_swp(RTE_PER_LCORE(_dpaa2_io).ethrx_dpio_dev);
 
-	pthread_setspecific(dpaa2_portal_key, NULL);
+	rte_thread_value_set(dpaa2_portal_key, NULL);
 }
 
 static int
@@ -515,10 +514,10 @@ dpaa2_create_dpio_device(int vdev_fd,
 		/* create the key, supplying a function that'll be invoked
 		 * when a portal affined thread will be deleted.
 		 */
-		ret = pthread_key_create(&dpaa2_portal_key,
+		ret = rte_thread_key_create(&dpaa2_portal_key,
 					 dpaa2_portal_finish);
 		if (ret) {
-			DPAA2_BUS_DEBUG("Unable to create pthread key (%d)",
+			DPAA2_BUS_DEBUG("Unable to create thread key (%d)",
 					ret);
 			goto err;
 		}
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index ec3c237512..d2bda960f8 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -73,7 +73,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -833,9 +833,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -855,13 +855,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index aa101a49a3..98ff0a26fc 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
@@ -192,7 +192,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 0c91a40c4a..20b51e15dd 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -178,7 +178,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -666,7 +666,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -677,7 +677,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -715,7 +715,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -741,7 +741,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -770,9 +770,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -938,9 +938,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 6372cf7740..0e4a7d0851 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -563,7 +563,7 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 473f6209f6..96b7da3ac7 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f326..93e41aa26a 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405c..15b80584f8 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -6,7 +6,7 @@
  */
 
 #include <rte_ether.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include "../atl_hw_regs.h"
 
 #include "../atl_types.h"
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_common.h b/drivers/net/axgbe/axgbe_common.h
index df0aa21a9b..a7b892b806 100644
--- a/drivers/net/axgbe/axgbe_common.h
+++ b/drivers/net/axgbe/axgbe_common.h
@@ -19,7 +19,7 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b0..197c722901 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index ebe9a2876d..e6f252e094 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729fe..cfd436fa63 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12e..c17f9a8b9e 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695ae..5f3d9b360e 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec192..1e1d6358d8 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index dfdfa9f7a0..b6a74753c5 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -533,8 +533,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -693,7 +693,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -747,18 +747,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -957,10 +957,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3d..a50511047c 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index f5d2dc8590..5bb63756aa 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1049,7 +1049,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1059,20 +1059,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1456,14 +1456,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1545,13 +1545,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1583,14 +1583,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4076,7 +4076,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4084,7 +4084,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4254,7 +4254,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4269,7 +4269,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5055,25 +5055,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5856,14 +5856,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d1..e1d980cf91 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index b224a7d2c2..3f22a55110 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef97..455d83bef8 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061a..88d64d703f 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd6831..26c3e7551c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea2..cb6bbcad6c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index a1d749f83f..f06bd2b279 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -129,14 +129,14 @@ do {                                                                   \
 #define q_waitqueue_t			\
 	struct {			\
 		pthread_cond_t cond;	\
-		pthread_mutex_t mutex;	\
+		rte_thread_mutex_t mutex;	\
 	}
 
 #define ena_wait_queue_t q_waitqueue_t
 
 #define ENA_WAIT_EVENT_INIT(waitqueue)					\
 	do {								\
-		pthread_mutex_init(&(waitqueue).mutex, NULL);		\
+		rte_thread_mutex_init(&(waitqueue).mutex);		\
 		pthread_cond_init(&(waitqueue).cond, NULL);		\
 	} while (0)
 
@@ -149,10 +149,10 @@ do {                                                                   \
 		wait.tv_sec = now.tv_sec + timeout / 1000000UL;		\
 		timeout_us = timeout % 1000000UL;			\
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	\
-		pthread_mutex_lock(&waitevent.mutex);			\
+		rte_thread_mutex_lock(&waitevent.mutex);		\
 		pthread_cond_timedwait(&waitevent.cond,			\
 				&waitevent.mutex, &wait);		\
-		pthread_mutex_unlock(&waitevent.mutex);			\
+		rte_thread_mutex_unlock(&waitevent.mutex);		\
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent) pthread_cond_signal(&waitevent.cond)
 /* pthread condition doesn't need to be rearmed after usage */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index cd66348f2f..1115afa81b 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index c8e433239b..5f7bd4a3fa 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -3,7 +3,7 @@
  */
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <unistd.h>
 
 #include <rte_spinlock.h>
@@ -154,7 +154,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 #define THREAD_NAME_LEN	16
 	struct ice_dcf_reset_event_param *param;
 	char name[THREAD_NAME_LEN];
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 589d9fa587..97e36a2e0e 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca24..272fdcfb8d 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 9ce74e549b..610ce7daa2 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -3,7 +3,7 @@
  */
 
 #include <fcntl.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <unistd.h>
 
 #include <rte_string_fns.h>
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 41622c1bf7..c540be96a7 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2534,7 +2534,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 7e13b38ee0..cb4386c36e 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -183,7 +183,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -981,7 +981,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1108,11 +1108,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1144,7 +1144,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1175,7 +1175,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1208,11 +1208,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2338,7 +2338,7 @@ RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index c9bc45cc1e..e8f657e7cc 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -817,7 +817,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index d90399afb5..e308c5e599 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -905,7 +905,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -921,7 +921,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -948,7 +948,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -956,7 +956,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index c4d5790726..229bad3ea7 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_thread_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 814063b5ce..be0169b2b2 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -228,7 +228,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b5399282..f0cb71c93d 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index d198fc8a8e..55f72d9532 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -3,7 +3,7 @@
  * Copyright(c) 2016-2018 Intel Corporation
  */
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <stdbool.h>
 #include <sys/epoll.h>
 
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 364f43e21c..9231da676b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -143,7 +143,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -161,7 +161,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -185,7 +185,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -206,12 +206,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -226,7 +226,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -249,11 +249,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -380,7 +380,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -405,7 +405,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -491,7 +491,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -796,13 +796,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -812,7 +812,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -837,7 +837,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 58ad5198b6..8c2df84d74 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -55,7 +55,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index f2551be821..ccd9b5a252 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 1dc813d0a3..7a90237ba2 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -3,7 +3,7 @@
  */
 
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/ioctl.h>
@@ -52,7 +52,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -79,7 +79,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -89,7 +89,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -98,7 +98,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -112,7 +112,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -122,7 +122,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -503,7 +503,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 	ret = rte_ctrl_thread_create(&internal->tid, name, NULL, notify_relay,
 				     (void *)internal);
 	if (ret != 0) {
-		DRV_LOG(ERR, "failed to create notify relay pthread.");
+		DRV_LOG(ERR, "failed to create notify relay thread.");
 		return -1;
 	}
 
@@ -513,13 +513,11 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
-	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+	if (internal->tid.opaque_id) {
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
-	internal->tid = 0;
+	internal->tid.opaque_id = 0;
 
 	if (internal->epfd >= 0)
 		close(internal->epfd);
@@ -809,7 +807,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 	ret = rte_ctrl_thread_create(&internal->tid, name, NULL, vring_relay,
 				     (void *)internal);
 	if (ret != 0) {
-		DRV_LOG(ERR, "failed to create ring relay pthread.");
+		DRV_LOG(ERR, "failed to create ring relay thread.");
 		return -1;
 	}
 
@@ -819,13 +817,11 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
-	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+	if (internal->tid.opaque_id) {
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
-	internal->tid = 0;
+	internal->tid.opaque_id = 0;
 
 	if (internal->epfd >= 0)
 		close(internal->epfd);
@@ -1253,9 +1249,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1293,9 +1289,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index 898e50f807..bcb744f5b6 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -764,10 +764,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -798,7 +798,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -807,7 +807,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -816,7 +816,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 			priv->var = NULL;
 		}
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index d93b430c97..568b84c3ff 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,10 +119,10 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t last_traffic_tic;
-	pthread_t timer_tid;
-	pthread_mutex_t timer_lock;
+	rte_thread_t timer_tid;
+	rte_thread_mutex_t timer_lock;
 	pthread_cond_t timer_cond;
 	volatile uint8_t timer_on;
 	int event_mode;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 404e135d5c..233436a97b 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -247,17 +247,17 @@ mlx5_vdpa_poll_handle(void *arg)
 	uint32_t max;
 	uint64_t current_tic;
 
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	while (!priv->timer_on)
 		pthread_cond_wait(&priv->timer_cond, &priv->timer_lock);
-	pthread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
 	priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
 								 priv->event_us;
 	while (1) {
 		max = 0;
-		pthread_mutex_lock(&priv->vq_config_lock);
+		rte_thread_mutex_lock(&priv->vq_config_lock);
 		for (i = 0; i < priv->nr_virtqs; i++) {
 			cq = &priv->virtqs[i].eqp.cq;
 			if (cq->cq_obj.cq && !cq->armed) {
@@ -281,13 +281,13 @@ mlx5_vdpa_poll_handle(void *arg)
 				DRV_LOG(DEBUG, "Device %s traffic was stopped.",
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
-				pthread_mutex_unlock(&priv->vq_config_lock);
-				pthread_mutex_lock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->timer_lock);
 				priv->timer_on = 0;
 				while (!priv->timer_on)
 					pthread_cond_wait(&priv->timer_cond,
 							  &priv->timer_lock);
-				pthread_mutex_unlock(&priv->timer_lock);
+				rte_thread_mutex_unlock(&priv->timer_lock);
 				priv->timer_delay_us = priv->event_mode ==
 					    MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ?
 					      MLX5_VDPA_DEFAULT_TIMER_DELAY_US :
@@ -297,7 +297,7 @@ mlx5_vdpa_poll_handle(void *arg)
 		} else {
 			priv->last_traffic_tic = current_tic;
 		}
-		pthread_mutex_unlock(&priv->vq_config_lock);
+		rte_thread_mutex_unlock(&priv->vq_config_lock);
 		mlx5_vdpa_timer_sleep(priv, max);
 	}
 	return NULL;
@@ -313,7 +313,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 		uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];
 	} out;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -332,7 +332,7 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 			eventfd_write(cq->callfd, (eventfd_t)1);
 		if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
 			mlx5_vdpa_cq_arm(priv, cq);
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			return;
 		}
 		/* Don't arm again - timer will take control. */
@@ -347,13 +347,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)
 
 	/* Traffic detected: make sure timer is on. */
 	priv->last_traffic_tic = rte_rdtsc();
-	pthread_mutex_lock(&priv->timer_lock);
+	rte_thread_mutex_lock(&priv->timer_lock);
 	if (!priv->timer_on) {
 		priv->timer_on = 1;
 		pthread_cond_signal(&priv->timer_cond);
 	}
-	pthread_mutex_unlock(&priv->timer_lock);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->timer_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 }
 
 static void
@@ -369,7 +369,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -415,7 +415,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -502,49 +502,41 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
 	if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) {
-		pthread_mutex_init(&priv->timer_lock, NULL);
+		rte_thread_mutex_init(&priv->timer_lock);
 		pthread_cond_init(&priv->timer_cond, NULL);
 		priv->timer_on = 0;
-		pthread_attr_init(&attr);
-		ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+		rte_thread_attr_init(&attr);
+		CPU_ZERO(&cpuset);
+		if (priv->event_core != -1)
+			CPU_SET(priv->event_core, &cpuset);
+		else
+			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
 		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+			DRV_LOG(ERR, "Failed to set thread affinity.");
 			return -1;
 		}
-		ret = pthread_attr_setschedparam(&attr, &sp);
+		ret = rte_thread_attr_set_priority(&attr,
+					RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set thread priority.");
 			return -1;
 		}
-		ret = pthread_create(&priv->timer_tid, &attr,
+		ret = rte_thread_create(&priv->timer_tid, &attr,
 				     mlx5_vdpa_poll_handle, (void *)priv);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create timer thread.");
 			return -1;
 		}
-		CPU_ZERO(&cpuset);
-		if (priv->event_core != -1)
-			CPU_SET(priv->event_core, &cpuset);
-		else
-			cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-		ret = pthread_setaffinity_np(priv->timer_tid,
-					     sizeof(cpuset), &cpuset);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to set thread affinity.");
-			goto error;
-		}
 		snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
-		ret = pthread_setname_np(priv->timer_tid, name);
+		ret = pthread_setname_np(priv->timer_tid.opaque_id, name);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to set timer thread name.");
 			return -1;
@@ -569,7 +561,6 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
 	int retries = MLX5_VDPA_INTR_RETRIES;
 	int ret = -EAGAIN;
-	void *status;
 
 	if (priv->intr_handle.fd) {
 		while (retries-- && ret == -EAGAIN) {
@@ -585,11 +576,11 @@ mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 		}
 		memset(&priv->intr_handle, 0, sizeof(priv->intr_handle));
 	}
-	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+	if (priv->timer_tid.opaque_id) {
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
-	priv->timer_tid = 0;
+	priv->timer_tid.opaque_id = 0;
 }
 
 void
diff --git a/examples/kni/main.c b/examples/kni/main.c
index beabb3c848..e4741f85ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/performance-thread/pthread_shim/main.c b/examples/performance-thread/pthread_shim/main.c
index 257de50692..bef7b59842 100644
--- a/examples/performance-thread/pthread_shim/main.c
+++ b/examples/performance-thread/pthread_shim/main.c
@@ -164,7 +164,7 @@ static void *initial_lthread(void *args __rte_unused)
 			rte_exit(EXIT_FAILURE, "Cannot create helloworld thread\n");
 
 		snprintf(name, sizeof(name), "helloworld-%u", (uint32_t)i);
-		rte_thread_setname(tid[i], name);
+		pthread_setname_np(tid[i], name);
 	}
 
 	/* wait for 1s to allow threads
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index ff48ba270d..da45b0d41f 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1635,7 +1635,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = 0;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index fe2b4e4803..6d96277eb3 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -5,7 +5,7 @@
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 #endif
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sched.h>
 
 #include <stdint.h>
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features, protocol_features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring, inflight_shmfd;
 
@@ -693,7 +693,7 @@ new_device(int vid)
 
 	/* device has been started */
 	ctrlr->started = 1;
-	pthread_detach(tid);
+	pthread_detach(tid.opaque_id);
 	return 0;
 }
 
diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index 773cefdff7..fb53b40840 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -1866,8 +1866,7 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1895,8 +1894,7 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/eal/common/eal_common_proc.c b/lib/eal/common/eal_common_proc.c
index 6d1af3c0e7..6eb2bbb3a0 100644
--- a/lib/eal/common/eal_common_proc.c
+++ b/lib/eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -527,9 +527,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -587,7 +587,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -999,9 +999,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1022,7 +1022,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1041,7 +1041,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1119,7 +1119,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1142,7 +1142,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1186,7 +1186,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1202,7 +1202,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/eal/common/eal_common_thread.c b/lib/eal/common/eal_common_thread.c
index 1a52f42a2b..f2dbc19191 100644
--- a/lib/eal/common/eal_common_thread.c
+++ b/lib/eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,8 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,14 +167,14 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 	unsigned int refcnt;
 };
 
 static void ctrl_params_free(struct rte_thread_ctrl_params *params)
 {
 	if (__atomic_sub_fetch(&params->refcnt, 1, __ATOMIC_ACQ_REL) == 0) {
-		(void)pthread_barrier_destroy(&params->configured);
+		(void)rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 }
@@ -192,7 +190,7 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	pthread_barrier_wait(&params->configured);
+	rte_thread_barrier_wait(&params->configured);
 	start_routine = params->start_routine;
 	ctrl_params_free(params);
 
@@ -203,8 +201,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -221,11 +219,11 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->arg = arg;
 	params->refcnt = 2;
 
-	ret = pthread_barrier_init(&params->configured, NULL, 2);
+	ret = rte_thread_barrier_init(&params->configured, 2);
 	if (ret != 0)
 		goto fail_no_barrier;
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, (void *)params);
 	if (ret != 0)
 		goto fail_with_barrier;
 
@@ -236,22 +234,22 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, cpuset);
 	if (ret != 0)
 		params->start_routine = NULL;
 
-	pthread_barrier_wait(&params->configured);
+	rte_thread_barrier_wait(&params->configured);
 	ctrl_params_free(params);
 
 	if (ret != 0)
 		/* start_routine has been set to NULL above; */
 		/* ctrl thread will exit immediately */
-		pthread_join(*thread, NULL);
+		rte_thread_join(*thread, NULL);
 
 	return -ret;
 
 fail_with_barrier:
-	(void)pthread_barrier_destroy(&params->configured);
+	(void)rte_thread_barrier_destroy(&params->configured);
 
 fail_no_barrier:
 	free(params);
@@ -276,8 +274,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
-			&cpuset) != 0)
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
 	if (lcore_id >= RTE_MAX_LCORE)
diff --git a/lib/eal/common/eal_common_trace.c b/lib/eal/common/eal_common_trace.c
index 24e27387b1..6df4a01277 100644
--- a/lib/eal/common/eal_common_trace.c
+++ b/lib/eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/eal/common/eal_private.h b/lib/eal/common/eal_private.h
index 64cf4e81c8..4b95001d7d 100644
--- a/lib/eal/common/eal_private.h
+++ b/lib/eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/eal/common/malloc_mp.c b/lib/eal/common/malloc_mp.c
index c7101b32d3..fdc3a2cfe6 100644
--- a/lib/eal/common/malloc_mp.c
+++ b/lib/eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -303,7 +303,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -389,10 +389,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -411,7 +411,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -541,10 +541,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -559,7 +559,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -590,10 +590,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -605,7 +605,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -618,7 +618,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -708,7 +708,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -769,10 +769,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/freebsd/eal.c b/lib/eal/freebsd/eal.c
index f4d1676754..1c862aa1cb 100644
--- a/lib/eal/freebsd/eal.c
+++ b/lib/eal/freebsd/eal.c
@@ -667,7 +667,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -690,7 +690,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -854,7 +854,14 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,10 +872,25 @@ rte_eal_init(int argc, char **argv)
 
 	ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
 
-	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (tid=%p;cpuset=[%s%s])\n",
-		config->main_lcore, thread_id, cpuset,
+	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (cpuset=[%s%s])\n",
+		config->main_lcore, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -882,8 +904,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -893,10 +917,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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/eal/freebsd/eal_alarm.c b/lib/eal/freebsd/eal_alarm.c
index c38b2e04f8..e5d7b130b1 100644
--- a/lib/eal/freebsd/eal_alarm.c
+++ b/lib/eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/eal/freebsd/eal_interrupts.c b/lib/eal/freebsd/eal_interrupts.c
index 86810845fe..c0bf6c882a 100644
--- a/lib/eal/freebsd/eal_interrupts.c
+++ b/lib/eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -737,5 +737,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/eal/freebsd/eal_thread.c b/lib/eal/freebsd/eal_thread.c
index 1dce9b04f2..cb8563cb7a 100644
--- a/lib/eal/freebsd/eal_thread.c
+++ b/lib/eal/freebsd/eal_thread.c
@@ -73,15 +73,15 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id, lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -93,8 +93,8 @@ eal_thread_loop(__rte_unused void *arg)
 	__rte_thread_init(lcore_id, &lcore_config[lcore_id].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 ? "" : "...");
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (cpuset=[%s%s])\n",
+		lcore_id, cpuset, ret == 0 ? "" : "...");
 
 	rte_eal_trace_thread_lcore_ready(lcore_id, cpuset);
 
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index 88a9eba12f..3b872f228f 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
         'rte_string_fns.h',
         'rte_tailq.h',
         'rte_thread.h',
+        'rte_thread_types.h',
         'rte_time.h',
         'rte_trace.h',
         'rte_trace_point.h',
diff --git a/lib/eal/include/rte_lcore.h b/lib/eal/include/rte_lcore.h
index 1550b75da0..d5e004105d 100644
--- a/lib/eal/include/rte_lcore.h
+++ b/lib/eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/eal/include/rte_per_lcore.h b/lib/eal/include/rte_per_lcore.h
index eaedf0cb37..025d97f962 100644
--- a/lib/eal/include/rte_per_lcore.h
+++ b/lib/eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c
index ba19fc6347..8ac2c99114 100644
--- a/lib/eal/linux/eal.c
+++ b/lib/eal/linux/eal.c
@@ -963,7 +963,6 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -991,7 +990,6 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1219,7 +1217,14 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1229,10 +1234,27 @@ rte_eal_init(int argc, char **argv)
 		&lcore_config[config->main_lcore].cpuset);
 
 	ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
-	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (tid=%zx;cpuset=[%s%s])\n",
-		config->main_lcore, (uintptr_t)thread_id, cpuset,
+	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (cpuset=[%s%s])\n",
+		config->main_lcore, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1246,9 +1268,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1260,11 +1284,6 @@ 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/eal/linux/eal_alarm.c b/lib/eal/linux/eal_alarm.c
index 3252c6fa59..fef22a347c 100644
--- a/lib/eal/linux/eal_alarm.c
+++ b/lib/eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/eal/linux/eal_interrupts.c b/lib/eal/linux/eal_interrupts.c
index 22b3b7bcd9..e106fa186c 100644
--- a/lib/eal/linux/eal_interrupts.c
+++ b/lib/eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1570,5 +1570,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/eal/linux/eal_thread.c b/lib/eal/linux/eal_thread.c
index 83c2034b93..fe6b02788f 100644
--- a/lib/eal/linux/eal_thread.c
+++ b/lib/eal/linux/eal_thread.c
@@ -73,15 +73,15 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id,lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -93,8 +93,8 @@ eal_thread_loop(__rte_unused void *arg)
 	__rte_thread_init(lcore_id, &lcore_config[lcore_id].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 ? "" : "...");
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (cpuset=[%s%s])\n",
+		lcore_id, cpuset, ret == 0 ? "" : "...");
 
 	rte_eal_trace_thread_lcore_ready(lcore_id, cpuset);
 
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -156,7 +156,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	char truncated[16];
 
 	strlcpy(truncated, name, sizeof(truncated));
-	ret = pthread_setname_np(id, truncated);
+	ret = pthread_setname_np(id.opaque_id, truncated);
 #endif
 #endif
 	RTE_SET_USED(id);
@@ -164,12 +164,12 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
 #if __GLIBC_PREREQ(2, 12)
-	ret = pthread_getname_np(id, name, len);
+	ret = pthread_getname_np(id.opaque_id, name, len);
 #endif
 #endif
 	RTE_SET_USED(id);
diff --git a/lib/eal/linux/eal_timer.c b/lib/eal/linux/eal_timer.c
index 7cf15cabac..b4099a0aa2 100644
--- a/lib/eal/linux/eal_timer.c
+++ b/lib/eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index dc711b4240..f2b8063760 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
         'eal_file.c',
         'eal_unix_memory.c',
         'eal_unix_timer.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c
deleted file mode 100644
index c72d619ec1..0000000000
--- a/lib/eal/unix/rte_thread.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_key_delete(rte_thread_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_value_set(rte_thread_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_value_get(rte_thread_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/eal/version.map b/lib/eal/version.map
index fe5c3dac98..902ad1ab65 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,27 @@ EXPERIMENTAL {
 	rte_version_release; # WINDOWS_NO_EXPORT
 	rte_version_suffix; # WINDOWS_NO_EXPORT
 	rte_version_year; # WINDOWS_NO_EXPORT
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel; # WINDOWS_NO_EXPORT
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c
index 28c787c0b0..533707ec72 100644
--- a/lib/eal/windows/eal.c
+++ b/lib/eal/windows/eal.c
@@ -375,6 +375,35 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			&lcore_config[config->main_lcore].cpuset) != 0) {
+		rte_eal_init_alert("Cannot set affinity");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -390,8 +419,17 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		ret = rte_thread_attr_set_affinity(&thread_attr, &lcore_config[i].cpuset);
+		if (ret != 0) {
+			rte_eal_init_alert("Cannot set thread affinity attribute");
+			rte_errno = ret;
+			return -1;
+		}
+
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/eal/windows/eal_interrupts.c b/lib/eal/windows/eal_interrupts.c
index 1d4cf794df..a529ef95e3 100644
--- a/lib/eal/windows/eal_interrupts.c
+++ b/lib/eal/windows/eal_interrupts.c
@@ -2,12 +2,14 @@
  * Copyright 2020 Mellanox Technologies, Ltd
  */
 
+#include <inttypes.h>
+
 #include <rte_interrupts.h>
 
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +78,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -92,9 +94,9 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 {
 	HANDLE handle;
 
-	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
+	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread.opaque_id);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread (%" PRIuPTR ")", intr_thread.opaque_id);
 		return -ENOENT;
 	}
 
diff --git a/lib/eal/windows/eal_thread.c b/lib/eal/windows/eal_thread.c
index 9c3f6d69fd..0c6bca24cf 100644
--- a/lib/eal/windows/eal_thread.c
+++ b/lib/eal/windows/eal_thread.c
@@ -60,15 +60,15 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id, lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -80,7 +80,7 @@ eal_thread_loop(void *arg __rte_unused)
 	__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);
+		lcore_id, thread_id.opaque_id, cpuset);
 
 	/* read on our pipe to get commands */
 	while (1) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index dc5dc8240a..4b92b198c7 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/eal/windows/include/meson.build b/lib/eal/windows/include/meson.build
index b3534b025f..7d9b3393e4 100644
--- a/lib/eal/windows/include/meson.build
+++ b/lib/eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/eal/windows/include/pthread.h b/lib/eal/windows/include/pthread.h
deleted file mode 100644
index 1939b0121c..0000000000
--- a/lib/eal/windows/include/pthread.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	!InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	!DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) !TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/meson.build b/lib/eal/windows/meson.build
index ff9cbec417..4b7db4754b 100644
--- a/lib/eal/windows/meson.build
+++ b/lib/eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
         'eal_timer.c',
         'fnmatch.c',
         'getopt.c',
-        'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'eal/common/rte_thread.c'
+else
+	sources += 'eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index a1879765e8..823d02b529 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -524,7 +524,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -598,7 +598,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/ethdev/rte_ethdev_core.h b/lib/ethdev/rte_ethdev_core.h
index 4679d948fa..ad1053b561 100644
--- a/lib/ethdev/rte_ethdev_core.h
+++ b/lib/ethdev/rte_ethdev_core.h
@@ -5,7 +5,8 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
+#include <rte_thread.h>
+#include <sys/types.h>
 
 /**
  * @file
@@ -182,7 +183,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index c7c7108933..2c0a8c0470 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -225,14 +225,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/eventdev/rte_event_eth_rx_adapter.c b/lib/eventdev/rte_event_eth_rx_adapter.c
index ca166a65f2..d3c49dac77 100644
--- a/lib/eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/eventdev/rte_event_eth_rx_adapter.c
@@ -147,7 +147,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1450,12 +1450,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c
index 55d4856f9e..b97774ccd4 100644
--- a/lib/vhost/fd_man.c
+++ b/lib/vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/vhost/fd_man.h b/lib/vhost/fd_man.h
index 3ab5cfdd60..ba58d849e8 100644
--- a/lib/vhost/fd_man.h
+++ b/lib/vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
index 0169d36481..faec3650fb 100644
--- a/lib/vhost/socket.c
+++ b/lib/vhost/socket.c
@@ -14,7 +14,7 @@
 #include <sys/queue.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_log.h>
 
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -73,7 +73,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -86,12 +86,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -269,9 +269,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -324,9 +324,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -418,11 +418,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -454,7 +454,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -485,7 +485,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -497,7 +497,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -508,7 +508,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -552,9 +552,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -586,11 +586,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -600,11 +600,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -615,11 +615,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -629,7 +629,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -639,7 +639,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -649,7 +649,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -657,12 +657,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -672,7 +672,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -683,7 +683,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -696,7 +696,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -722,7 +722,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -732,11 +732,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -749,7 +749,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -777,7 +777,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -789,7 +789,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -815,7 +815,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -847,7 +847,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -867,7 +867,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -948,7 +948,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
-		if (vsocket->reconnect && reconn_tid == 0) {
+		if (vsocket->reconnect && reconn_tid.opaque_id == 0) {
 			if (vhost_user_reconnect_init() != 0)
 				goto out_mutex;
 		}
@@ -962,18 +962,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -984,7 +984,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -998,7 +998,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1016,13 +1016,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1036,9 +1036,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1050,7 +1051,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1060,7 +1061,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1070,18 +1072,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1095,11 +1097,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1109,9 +1111,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1120,16 +1122,16 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
 
-	if (fdset_tid == 0) {
+	if (fdset_tid.opaque_id == 0) {
 		/**
 		 * create a pipe which will be waited by poll and notified to
 		 * rebuild the wait list of poll.
diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c
index a70fe01d8f..a9264d01fd 100644
--- a/lib/vhost/vhost.c
+++ b/lib/vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -656,7 +656,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -665,7 +665,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -673,12 +673,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 56bdfd0f0a..46d156cf2f 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -42,5 +42,7 @@ option('enable_trace_fp', type: 'boolean', value: false, description:
        'enable fast path trace points.')
 option('tests', type: 'boolean', value: true, description:
        'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false, description:
        'use HPET timer in EAL')
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-06-02 15:50                       ` Tal Shnaiderman
  2021-06-02 16:16                         ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Tal Shnaiderman @ 2021-06-02 15:50 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile, dev, NBU-Contact-Thomas Monjalon,
	dmitry.kozliuk, khot, navasile, dmitrym, roretzla, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

> Subject: [PATCH v7 10/10] Enable the new EAL thread API
> 
> External email: Use caution opening links or attachments
> 
> 
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Rename pthread_* occurrences with the new rte_thread_* API.
> Enable the new API in the build system.
> ---

Hi Naty,

I wanted to run some basic tests on your series but I cannot apply this patch.

Same issue in CI (http://mails.dpdk.org/archives/test-report/2021-June/197522.html)

Can you send a rebased version?

Thanks,

Tal.
	

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API
  2021-06-02 15:50                       ` Tal Shnaiderman
@ 2021-06-02 16:16                         ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-02 16:16 UTC (permalink / raw)
  To: Tal Shnaiderman
  Cc: dev, NBU-Contact-Thomas Monjalon, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Wed, Jun 02, 2021 at 03:50:02PM +0000, Tal Shnaiderman wrote:
> > Subject: [PATCH v7 10/10] Enable the new EAL thread API
> > 
> > External email: Use caution opening links or attachments
> > 
> > 
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Rename pthread_* occurrences with the new rte_thread_* API.
> > Enable the new API in the build system.
> > ---
> 
> Hi Naty,
> 
> I wanted to run some basic tests on your series but I cannot apply this patch.
> 
> Same issue in CI (http://mails.dpdk.org/archives/test-report/2021-June/197522.html)
> 
> Can you send a rebased version?
> 

Thanks Tal, I will rebase.

> Thanks,
> 
> Tal.
> 	

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading
  2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
                                       ` (9 preceding siblings ...)
  2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                     ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                                         ` (10 more replies)
  10 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   8 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   5 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/dpaa/dpaa_bus.c                   |  14 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  19 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   4 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   2 +-
 drivers/net/ark/ark_pktgen.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  26 +-
 drivers/net/axgbe/axgbe_common.h              |   2 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |  12 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   6 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   8 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  24 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   6 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  46 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   4 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  46 +-
 examples/kni/main.c                           |   6 +-
 .../performance-thread/pthread_shim/main.c    |   2 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  12 +-
 lib/eal/common/eal_common_options.c           |  34 +-
 lib/eal/common/eal_common_proc.c              |  48 +-
 lib/eal/common/eal_common_thread.c            |  42 +-
 lib/eal/common/eal_common_trace.c             |   2 +-
 lib/eal/common/eal_internal_cfg.h             |   2 +
 lib/eal/common/eal_options.h                  |   2 +
 lib/eal/common/eal_private.h                  |   2 +-
 lib/eal/common/eal_thread.h                   |   6 +
 lib/eal/common/malloc_mp.c                    |  32 +-
 lib/eal/common/meson.build                    |   1 +
 lib/eal/common/rte_thread.c                   | 422 +++++++++++
 lib/eal/freebsd/eal.c                         |  42 +-
 lib/eal/freebsd/eal_alarm.c                   |  12 +-
 lib/eal/freebsd/eal_interrupts.c              |   4 +-
 lib/eal/freebsd/eal_thread.c                  |  14 +-
 lib/eal/include/meson.build                   |   1 +
 lib/eal/include/rte_lcore.h                   |   8 +-
 lib/eal/include/rte_per_lcore.h               |   2 -
 lib/eal/include/rte_thread.h                  | 378 +++++++++-
 lib/eal/include/rte_thread_types.h            |  14 +
 lib/eal/linux/eal.c                           |  46 +-
 lib/eal/linux/eal_alarm.c                     |  10 +-
 lib/eal/linux/eal_interrupts.c                |   4 +-
 lib/eal/linux/eal_thread.c                    |  18 +-
 lib/eal/linux/eal_timer.c                     |   2 +-
 lib/eal/unix/meson.build                      |   1 -
 lib/eal/unix/rte_thread.c                     |  92 ---
 lib/eal/version.map                           |  22 +
 lib/eal/windows/eal.c                         |  43 +-
 lib/eal/windows/eal_interrupts.c              |  10 +-
 lib/eal/windows/eal_lcore.c                   | 169 +++--
 lib/eal/windows/eal_thread.c                  |  28 +-
 lib/eal/windows/eal_windows.h                 |  20 +-
 lib/eal/windows/include/meson.build           |   1 +
 lib/eal/windows/include/pthread.h             | 192 -----
 .../include/rte_windows_thread_types.h        |  19 +
 lib/eal/windows/include/sched.h               |   2 +-
 lib/eal/windows/meson.build                   |   7 +-
 lib/eal/windows/rte_thread.c                  | 678 +++++++++++++++++-
 lib/ethdev/rte_ethdev.c                       |   4 +-
 lib/ethdev/rte_ethdev_core.h                  |   5 +-
 lib/ethdev/rte_flow.c                         |   4 +-
 lib/eventdev/rte_event_eth_rx_adapter.c       |   6 +-
 lib/vhost/fd_man.c                            |  40 +-
 lib/vhost/fd_man.h                            |   6 +-
 lib/vhost/socket.c                            | 130 ++--
 lib/vhost/vhost.c                             |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2345 insertions(+), 967 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 create mode 100644 lib/eal/include/rte_thread_types.h
 delete mode 100644 lib/eal/unix/rte_thread.c
 delete mode 100644 lib/eal/windows/include/pthread.h
 create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 01/10] eal: add thread id and simple thread functions
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                         ` (9 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.
---
 lib/eal/common/rte_thread.c                   | 105 ++++++++++++++++++
 lib/eal/include/rte_thread.h                  |  53 +++++++--
 lib/eal/include/rte_thread_types.h            |  10 ++
 .../include/rte_windows_thread_types.h        |  10 ++
 lib/eal/windows/rte_thread.c                  |  17 +++
 5 files changed, 186 insertions(+), 9 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 create mode 100644 lib/eal/include/rte_thread_types.h
 create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
new file mode 100644
index 0000000000..1292f7a8f8
--- /dev/null
+++ b/lib/eal/common/rte_thread.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id = { 0 };
+
+	thread_id.opaque_id = pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1.opaque_id, t2.opaque_id);
+}
+
+int
+rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_thread_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_key_delete(rte_thread_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_value_set(rte_thread_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_value_get(rte_thread_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..347df1a6ae 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,50 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +104,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +119,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +134,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
new file mode 100644
index 0000000000..d67b24a563
--- /dev/null
+++ b/lib/eal/include/rte_thread_types.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 0000000000..60e6d94553
--- /dev/null
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..3f3ebba21f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id = { 0 };
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 02/10] eal: add thread attributes
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                         ` (8 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the already known “rte_cpuset_t” type.

An rte_thread_attr_t object can be set to the default values
by calling *rte_thread_attr_init()*.
---
 lib/eal/common/rte_thread.c                   | 51 +++++++++++
 lib/eal/include/rte_thread.h                  | 89 +++++++++++++++++++
 lib/eal/include/rte_thread_types.h            |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/eal/windows/rte_thread.c                  | 53 +++++++++++
 5 files changed, 199 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 1292f7a8f8..4b1e8f995e 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,56 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1.opaque_id, t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_ASSERT(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 347df1a6ae..eff00023d7 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -36,6 +36,26 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -66,6 +86,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index d67b24a563..996232c636 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,4 +7,7 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 60e6d94553..5bdeaad3d4 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,4 +7,7 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 3f3ebba21f..cc319d3628 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -5,6 +5,7 @@
 
 #include <rte_common.h>
 #include <rte_errno.h>
+#include <rte_debug.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
 
@@ -28,6 +29,58 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_ASSERT(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 03/10] eal/windows: translate Windows errors to errno-style errors
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                         ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.
---
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 90 +++++++++++++++++++++++++++---------
 2 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index eff00023d7..f3eeb28753 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -236,9 +236,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index cc319d3628..6ea1dc2a05 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char* message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -85,18 +133,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -104,16 +152,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -122,19 +170,17 @@ rte_thread_key_delete(rte_thread_key key)
 int
 rte_thread_value_set(rte_thread_key key, const void *value)
 {
+	int ret;
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -143,16 +189,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 04/10] eal: implement functions for thread affinity management
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (2 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-08 23:04                         ` Dmitry Kozlyuk
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                         ` (6 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.
---
 lib/eal/common/rte_thread.c   |  14 +++
 lib/eal/include/rte_thread.h  |  36 ++++++++
 lib/eal/windows/eal_lcore.c   | 169 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 127 ++++++++++++++++++++++++-
 5 files changed, 310 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 4b1e8f995e..ceb27feaa7 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,20 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1.opaque_id, t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index f3eeb28753..1f02962146 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -86,6 +86,42 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..519a62b96d 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +177,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +209,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +235,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 478accc1b9..dc5dc8240a 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 6ea1dc2a05..9e74a538c2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_errno.h>
 #include <rte_debug.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,130 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 05/10] eal: implement thread priority management functions
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (3 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                         ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL
---
 lib/eal/common/rte_thread.c                   | 51 ++++++++++
 lib/eal/include/rte_thread.h                  | 17 ++++
 lib/eal/include/rte_thread_types.h            |  3 -
 .../include/rte_windows_thread_types.h        |  3 -
 lib/eal/windows/rte_thread.c                  | 92 +++++++++++++++++++
 5 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ceb27feaa7..5cee19bb7d 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -48,6 +48,57 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri, int *pol)
+{
+	RTE_VERIFY(os_pri != NULL);
+	RTE_VERIFY(pol != NULL);
+
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri)
+	{
+		case RTE_THREAD_PRIORITY_NORMAL:
+			*pol = SCHED_OTHER;
+
+			/*
+			 * Choose the middle of the range to represent
+			 * the priority 'normal'.
+			 * On Linux, this should be 0, since both
+			 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+			 */
+			*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2;
+			break;
+		case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+			*pol = SCHED_RR;
+			*os_pri = sched_get_priority_max(SCHED_RR);
+			break;
+		default:
+			RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+			return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority, &policy);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return pthread_setschedparam(thread_id.opaque_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 1f02962146..5c54cd9d67 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -122,6 +122,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index 996232c636..d67b24a563 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,7 +7,4 @@
 
 #include <pthread.h>
 
-#define EAL_THREAD_PRIORITY_NORMAL               0
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
-
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 5bdeaad3d4..60e6d94553 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,7 +7,4 @@
 
 #include <rte_windows.h>
 
-#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
-
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 9e74a538c2..6dc3d575c0 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -202,6 +202,98 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	RTE_VERIFY(os_pri != NULL);
+	RTE_VERIFY(pri_class != NULL);
+
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri)
+	{
+		case RTE_THREAD_PRIORITY_NORMAL:
+			*pri_class = NORMAL_PRIORITY_CLASS;
+			*os_pri = THREAD_PRIORITY_NORMAL;
+			break;
+		case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+			*pri_class = REALTIME_PRIORITY_CLASS;
+			*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+			break;
+		default:
+			RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+			return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	int priority_class = NORMAL_PRIORITY_CLASS;
+	int os_priority = THREAD_PRIORITY_NORMAL;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority, &priority_class);
+	if (ret != 0) {
+		return ret;
+	}
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = thread_log_last_error("OpenProcess()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 06/10] eal: add thread lifetime management
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (4 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                         ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling, detaching.

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.
---
 lib/eal/common/rte_thread.c  | 116 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  67 +++++++++++++++
 lib/eal/windows/rte_thread.c | 162 +++++++++++++++++++++++++++++++++++
 3 files changed, 345 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 5cee19bb7d..84050d0f4c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -149,6 +149,122 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(&thread_id->opaque_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id.opaque_id);
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach(thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5c54cd9d67..1d481b9ad5 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -208,6 +208,73 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 		enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
+/**
+ * Detaches a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
+
 #ifdef RTE_HAS_CPUSET
 
 /**
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 6dc3d575c0..5afdd54e15 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	void* (*start_routine) (void*);
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -346,6 +351,163 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	intptr_t func_ret = 0;
+	struct thread_routine_ctx ctx = { NULL, NULL };
+
+	ctx.start_routine = pctx->start_routine;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (intptr_t)ctx.start_routine(ctx.routine_args);
+	return (DWORD)func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	DWORD tid = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->start_routine = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = thread_log_last_error("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	(void)thread_id;
+	return ENOTSUP;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 07/10] eal: implement functions for mutex management
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (5 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                         ` (3 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

On Linux, static initialization of a mutex is possible
through PTHREAD_MUTEX_INITIALIZER.

Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

To simulate static initialization, a fake initializator has been added:
The rte_mutex_lock() function will verify if the mutex has been initialized
using this fake initializer and if so, it will perform additional
initialization.
---
 lib/eal/common/rte_thread.c                   | 24 ++++++
 lib/eal/include/rte_thread.h                  | 53 ++++++++++++
 lib/eal/include/rte_thread_types.h            |  4 +
 .../include/rte_windows_thread_types.h        |  9 ++
 lib/eal/windows/rte_thread.c                  | 83 ++++++++++++++++++-
 5 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 84050d0f4c..4d7d9242a9 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -249,6 +249,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 1d481b9ad5..db8ef20930 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -248,6 +248,58 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
@@ -283,6 +335,7 @@ int rte_thread_detach(rte_thread_t thread_id);
  *
  * @param cpusetp
  *   Pointer to CPU affinity to set.
+ *
  * @return
  *   On success, return 0; otherwise return -1;
  */
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index d67b24a563..7bb0d2948c 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,4 +7,8 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
+typedef pthread_mutex_t                 rte_thread_mutex_t;
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 60e6d94553..c6c8502bfb 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,4 +7,13 @@
 
 #include <rte_windows.h>
 
+#define WINDOWS_MUTEX_INITIALIZER               (void*)-1
+#define RTE_THREAD_MUTEX_INITIALIZER            {WINDOWS_MUTEX_INITIALIZER}
+
+struct thread_mutex_t {
+	void* mutex_id;
+};
+
+typedef struct thread_mutex_t rte_thread_mutex_t;
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5afdd54e15..239aa6be5d 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -470,6 +470,88 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	int ret = 0;
+	void* id = 0;
+	rte_thread_mutex_t m;
+
+	RTE_VERIFY(mutex != NULL);
+
+	/* Check if mutex has been statically initialized */
+	id = InterlockedCompareExchangePointer(&mutex->mutex_id, mutex->mutex_id, WINDOWS_MUTEX_INITIALIZER);
+	/* If mutex has been statically initialized */
+	if (id == WINDOWS_MUTEX_INITIALIZER) {
+		ret = rte_thread_mutex_init(&m);
+		if (ret != 0) {
+			return ret;
+		}
+
+		id = InterlockedCompareExchangePointer(&mutex->mutex_id, m.mutex_id, WINDOWS_MUTEX_INITIALIZER);
+		/* If meanwhile the mutex was initialized by a different thread,
+		 * destroy the local initialization.
+		 */
+		if (id != WINDOWS_MUTEX_INITIALIZER) {
+			rte_thread_mutex_destroy(&m);
+		}
+	}
+
+	EnterCriticalSection(mutex->mutex_id);
+
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (mutex->mutex_id == WINDOWS_MUTEX_INITIALIZER) {
+		goto cleanup;
+	}
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+
+cleanup:
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
@@ -549,7 +631,6 @@ rte_thread_key_delete(rte_thread_key key)
 int
 rte_thread_value_set(rte_thread_key key, const void *value)
 {
-	int ret;
 	char *p;
 
 	if (key == NULL) {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 08/10] eal: implement functions for thread barrier management
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (6 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                         ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 4d7d9242a9..0a9813794a 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -273,6 +273,67 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return ret;
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to destroy barrier, ret = %d\n", ret);
+	}
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index db8ef20930..b06443cf23 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -29,6 +29,11 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
 /**
  * Thread id descriptor.
  */
@@ -56,6 +61,13 @@ typedef struct {
 	rte_cpuset_t cpuset; /**< thread affinity */
 } rte_thread_attr_t;
 
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void* barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -300,6 +312,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 239aa6be5d..2e657bbde8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -552,6 +552,62 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 09/10] eal: add EAL argument for setting thread priority
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (7 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ff5861b5f3..9d29696b84 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2088,6 +2113,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v8 10/10] Enable the new EAL thread API
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (8 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-06-04 23:38                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:38 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.
---
 app/test/process.h                            |   8 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   5 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/dpaa/dpaa_bus.c                   |  14 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  19 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   4 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   2 +-
 drivers/net/ark/ark_pktgen.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  26 +--
 drivers/net/axgbe/axgbe_common.h              |   2 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |  12 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   6 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   8 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  24 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   6 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  46 ++---
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   4 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  46 ++---
 examples/kni/main.c                           |   6 +-
 .../performance-thread/pthread_shim/main.c    |   2 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  12 +-
 lib/eal/common/eal_common_options.c           |   6 +-
 lib/eal/common/eal_common_proc.c              |  48 ++---
 lib/eal/common/eal_common_thread.c            |  42 ++--
 lib/eal/common/eal_common_trace.c             |   2 +-
 lib/eal/common/eal_private.h                  |   2 +-
 lib/eal/common/eal_thread.h                   |   6 +
 lib/eal/common/malloc_mp.c                    |  32 +--
 lib/eal/common/meson.build                    |   1 +
 lib/eal/freebsd/eal.c                         |  42 +++-
 lib/eal/freebsd/eal_alarm.c                   |  12 +-
 lib/eal/freebsd/eal_interrupts.c              |   4 +-
 lib/eal/freebsd/eal_thread.c                  |  14 +-
 lib/eal/include/meson.build                   |   1 +
 lib/eal/include/rte_lcore.h                   |   8 +-
 lib/eal/include/rte_per_lcore.h               |   2 -
 lib/eal/linux/eal.c                           |  46 +++--
 lib/eal/linux/eal_alarm.c                     |  10 +-
 lib/eal/linux/eal_interrupts.c                |   4 +-
 lib/eal/linux/eal_thread.c                    |  18 +-
 lib/eal/linux/eal_timer.c                     |   2 +-
 lib/eal/unix/meson.build                      |   1 -
 lib/eal/unix/rte_thread.c                     |  92 ---------
 lib/eal/version.map                           |  22 ++
 lib/eal/windows/eal.c                         |  43 +++-
 lib/eal/windows/eal_interrupts.c              |  10 +-
 lib/eal/windows/eal_thread.c                  |  28 +--
 lib/eal/windows/eal_windows.h                 |  10 -
 lib/eal/windows/include/meson.build           |   1 +
 lib/eal/windows/include/pthread.h             | 192 ------------------
 lib/eal/windows/include/sched.h               |   2 +-
 lib/eal/windows/meson.build                   |   7 +-
 lib/ethdev/rte_ethdev.c                       |   4 +-
 lib/ethdev/rte_ethdev_core.h                  |   5 +-
 lib/ethdev/rte_flow.c                         |   4 +-
 lib/eventdev/rte_event_eth_rx_adapter.c       |   6 +-
 lib/vhost/fd_man.c                            |  40 ++--
 lib/vhost/fd_man.h                            |   6 +-
 lib/vhost/socket.c                            | 130 ++++++------
 lib/vhost/vhost.c                             |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 703 insertions(+), 887 deletions(-)
 delete mode 100644 lib/eal/unix/rte_thread.c
 delete mode 100644 lib/eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index a09a088477..9e4be17bad 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -26,7 +26,7 @@
 
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-#include <pthread.h>
+#include <rte_thread.h>
 extern void *send_pkts(void *empty);
 extern uint16_t flag_for_send_pkts;
 #endif
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 	int rc;
 #endif
 #endif
@@ -128,7 +128,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
-		rc = pthread_create(&thread, NULL, &send_pkts, NULL);
+		rc = rte_thread_create(&thread, NULL, &send_pkts, NULL);
 		if (rc != 0) {
 			rte_panic("Cannot start send pkts thread: %s\n",
 				  strerror(rc));
@@ -143,7 +143,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fce..c507e423e0 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a8..3d9663f5ee 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d064..ce79d9c17a 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 017bb2efbb..4070eb200d 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -262,6 +262,10 @@ else # for 32-bit we need smaller reserved memory areas
     dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da1..c66a0946ca 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,10 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a2..dc5f02bec1 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681cd..6d2d10cdf0 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 2f48d4036b..bd83cab577 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -10,7 +10,7 @@
 #include <limits.h>
 #include <sched.h>
 #include <signal.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
 #include <sys/eventfd.h>
@@ -48,7 +48,7 @@ static struct rte_dpaa_bus rte_dpaa_bus;
 struct netcfg_info *dpaa_netcfg;
 
 /* define a variable to hold the portal_key, once created.*/
-static pthread_key_t dpaa_portal_key;
+static rte_thread_key dpaa_portal_key;
 
 unsigned int dpaa_svr_family;
 
@@ -316,10 +316,10 @@ int rte_dpaa_portal_init(void *arg)
 	DPAA_PER_LCORE_PORTAL->bman_idx = bman_get_portal_index();
 	DPAA_PER_LCORE_PORTAL->tid = syscall(SYS_gettid);
 
-	ret = pthread_setspecific(dpaa_portal_key,
+	ret = rte_thread_value_set(dpaa_portal_key,
 				  (void *)DPAA_PER_LCORE_PORTAL);
 	if (ret) {
-		DPAA_BUS_LOG(ERR, "pthread_setspecific failed on core %u"
+		DPAA_BUS_LOG(ERR, "rte_thread_value_set failed on core %u"
 			     " (lcore=%u) with ret: %d", cpu, lcore, ret);
 		dpaa_portal_finish(NULL);
 
@@ -377,7 +377,7 @@ dpaa_portal_finish(void *arg)
 	bman_thread_finish();
 	qman_thread_finish();
 
-	pthread_setspecific(dpaa_portal_key, NULL);
+	rte_thread_value_set(dpaa_portal_key, NULL);
 
 	rte_free(dpaa_io_portal);
 	dpaa_io_portal = NULL;
@@ -453,9 +453,9 @@ rte_dpaa_bus_scan(void)
 	/* create the key, supplying a function that'll be invoked
 	 * when a portal affined thread will be deleted.
 	 */
-	ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
+	ret = rte_thread_key_create(&dpaa_portal_key, dpaa_portal_finish);
 	if (ret) {
-		DPAA_BUS_LOG(DEBUG, "Unable to create pthread key. (%d)", ret);
+		DPAA_BUS_LOG(DEBUG, "Unable to create thread key. (%d)", ret);
 		dpaa_clean_device_list();
 		return ret;
 	}
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1d..dffbdff666 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -13,7 +13,7 @@
 #include <stdarg.h>
 #include <inttypes.h>
 #include <signal.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <sys/ioctl.h>
@@ -59,7 +59,7 @@ uint8_t dpaa2_dqrr_size;
 uint8_t dpaa2_eqcr_size;
 
 /* Variable to hold the portal_key, once created.*/
-static pthread_key_t dpaa2_portal_key;
+static rte_thread_key dpaa2_portal_key;
 
 /*Stashing Macros default for LS208x*/
 static int dpaa2_core_cluster_base = 0x04;
@@ -92,10 +92,9 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
@@ -296,9 +295,9 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(void)
 		}
 	}
 
-	ret = pthread_setspecific(dpaa2_portal_key, (void *)dpio_dev);
+	ret = rte_thread_value_set(dpaa2_portal_key, (void *)dpio_dev);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_setspecific failed with ret: %d", ret);
+		DPAA2_BUS_ERR("rte_thread_value_set failed with ret: %d", ret);
 		dpaa2_put_qbman_swp(dpio_dev);
 		return NULL;
 	}
@@ -357,7 +356,7 @@ static void dpaa2_portal_finish(void *arg)
 	dpaa2_put_qbman_swp(RTE_PER_LCORE(_dpaa2_io).dpio_dev);
 	dpaa2_put_qbman_swp(RTE_PER_LCORE(_dpaa2_io).ethrx_dpio_dev);
 
-	pthread_setspecific(dpaa2_portal_key, NULL);
+	rte_thread_value_set(dpaa2_portal_key, NULL);
 }
 
 static int
@@ -515,10 +514,10 @@ dpaa2_create_dpio_device(int vdev_fd,
 		/* create the key, supplying a function that'll be invoked
 		 * when a portal affined thread will be deleted.
 		 */
-		ret = pthread_key_create(&dpaa2_portal_key,
+		ret = rte_thread_key_create(&dpaa2_portal_key,
 					 dpaa2_portal_finish);
 		if (ret) {
-			DPAA2_BUS_DEBUG("Unable to create pthread key (%d)",
+			DPAA2_BUS_DEBUG("Unable to create thread key (%d)",
 					ret);
 			goto err;
 		}
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index 80c564f10b..b1f14ea606 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -72,7 +72,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -804,9 +804,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -826,13 +826,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index cffe22f3c5..bdd174821c 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
@@ -194,7 +194,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index eb5660a3dc..41fe063639 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -178,7 +178,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -676,7 +676,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -687,7 +687,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -725,7 +725,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -751,7 +751,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -780,9 +780,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -948,9 +948,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 377299b14c..481442b31e 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -563,7 +563,7 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
diff --git a/drivers/net/ark/ark_pktgen.c b/drivers/net/ark/ark_pktgen.c
index 515bfe461c..58ff65b5d5 100644
--- a/drivers/net/ark/ark_pktgen.c
+++ b/drivers/net/ark/ark_pktgen.c
@@ -3,7 +3,7 @@
  */
 
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
@@ -475,7 +475,7 @@ ark_pktgen_delay_start(void *arg)
 	 * perform a blind sleep here to ensure that the external test
 	 * application has time to setup the test before we generate packets
 	 */
-	pthread_detach(pthread_self());
+	rte_thread_detach(rte_thread_self());
 	usleep(100000);
 	ark_pktgen_run(inst);
 	return NULL;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 0ce35eb519..2b86f01a25 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f326..93e41aa26a 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405c..15b80584f8 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -6,7 +6,7 @@
  */
 
 #include <rte_ether.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include "../atl_hw_regs.h"
 
 #include "../atl_types.h"
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_common.h b/drivers/net/axgbe/axgbe_common.h
index df0aa21a9b..a7b892b806 100644
--- a/drivers/net/axgbe/axgbe_common.h
+++ b/drivers/net/axgbe/axgbe_common.h
@@ -19,7 +19,7 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b0..197c722901 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 9cb4818af1..caf5a4476f 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729fe..cfd436fa63 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12e..c17f9a8b9e 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695ae..5f3d9b360e 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec192..1e1d6358d8 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index db67bff127..64678ee145 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -534,8 +534,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -687,7 +687,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -741,18 +741,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -944,10 +944,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3d..a50511047c 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 3778e28cca..d00c8011ba 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1049,7 +1049,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1059,20 +1059,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1456,14 +1456,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1545,13 +1545,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1583,14 +1583,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4108,7 +4108,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4116,7 +4116,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4292,7 +4292,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4307,7 +4307,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5093,25 +5093,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5894,14 +5894,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d1..e1d980cf91 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index bdbad53b7d..49d3ec66bc 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef97..455d83bef8 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061a..88d64d703f 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd6831..26c3e7551c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea2..cb6bbcad6c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index f66df95591..923cef1b12 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -148,14 +148,14 @@ extern int ena_logtype_com;
 
 typedef struct {
 	pthread_cond_t cond;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 	uint8_t flag;
 } ena_wait_event_t;
 
 #define ENA_WAIT_EVENT_INIT(waitevent)					       \
 	do {								       \
 		ena_wait_event_t *_we = &(waitevent);			       \
-		pthread_mutex_init(&_we->mutex, NULL);			       \
+		rte_thread_mutex_init(&_we->mutex);				       \
 		pthread_cond_init(&_we->cond, NULL);			       \
 		_we->flag = 0;						       \
 	} while (0)
@@ -172,7 +172,7 @@ typedef struct {
 		wait.tv_sec = now.tv_sec + _tmo / 1000000UL;		       \
 		timeout_us = _tmo % 1000000UL;				       \
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	       \
-		pthread_mutex_lock(&_we->mutex);			       \
+		rte_thread_mutex_lock(&_we->mutex);			       \
 		while (ret == 0 && !_we->flag) {			       \
 			ret = pthread_cond_timedwait(&_we->cond,	       \
 				&_we->mutex, &wait);			       \
@@ -185,15 +185,15 @@ typedef struct {
 			ena_trc_err(NULL,				       \
 				"Timeout waiting for " #waitevent "\n");       \
 		_we->flag = 0;						       \
-		pthread_mutex_unlock(&_we->mutex);			       \
+		rte_thread_mutex_unlock(&_we->mutex);			       \
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent)				       \
 	do {								       \
 		ena_wait_event_t *_we = &(waitevent);			       \
-		pthread_mutex_lock(&_we->mutex);			       \
+		rte_thread_mutex_lock(&_we->mutex);			       \
 		_we->flag = 1;						       \
 		pthread_cond_signal(&_we->cond);			       \
-		pthread_mutex_unlock(&_we->mutex);			       \
+		rte_thread_mutex_unlock(&_we->mutex);			       \
 	} while (0)
 /* pthread condition doesn't need to be rearmed after usage */
 #define ENA_WAIT_EVENT_CLEAR(...)
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 47bfdac2cf..db07c589b9 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 1d7aa8bc87..99eb940b87 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -3,7 +3,7 @@
  */
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <unistd.h>
 
 #include <rte_spinlock.h>
@@ -121,7 +121,7 @@ ice_dcf_vsi_update_service_handler(void *param)
 	struct ice_dcf_hw *hw = reset_param->dcf_hw;
 	struct ice_dcf_adapter *adapter;
 
-	pthread_detach(pthread_self());
+	rte_thread_detach(rte_thread_self());
 
 	rte_delay_us(ICE_DCF_VSI_UPDATE_SERVICE_INTERVAL);
 
@@ -156,7 +156,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 #define THREAD_NAME_LEN	16
 	struct ice_dcf_reset_event_param *param;
 	char name[THREAD_NAME_LEN];
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 589d9fa587..97e36a2e0e 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b5371568b5..33c82474ad 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4156,7 +4156,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	rte_thread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca24..272fdcfb8d 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 871d11c413..5026305362 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -3,7 +3,7 @@
  */
 
 #include <fcntl.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <unistd.h>
 
 #include <rte_string_fns.h>
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 534a56a555..15080bbc1c 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2557,7 +2557,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index cf1815cb74..5858659183 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -183,7 +183,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -1088,7 +1088,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1215,11 +1215,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1251,7 +1251,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1282,7 +1282,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1315,11 +1315,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2450,7 +2450,7 @@ RTE_LOG_REGISTER_DEFAULT(mlx5_logtype, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 32b2817bf2..74df9f4355 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -949,7 +949,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index d90399afb5..e308c5e599 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -905,7 +905,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -921,7 +921,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -948,7 +948,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -956,7 +956,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index c4d5790726..229bad3ea7 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_thread_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 3fe3f55f49..e37e16d70f 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -228,7 +228,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b5399282..f0cb71c93d 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a202931e9a..cbab53fb51 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -3,7 +3,7 @@
  * Copyright(c) 2016-2018 Intel Corporation
  */
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <stdbool.h>
 #include <sys/epoll.h>
 
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 364f43e21c..9231da676b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -143,7 +143,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -161,7 +161,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -185,7 +185,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -206,12 +206,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -226,7 +226,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -249,11 +249,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -380,7 +380,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -405,7 +405,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -491,7 +491,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -796,13 +796,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -812,7 +812,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -837,7 +837,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 58ad5198b6..8c2df84d74 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -55,7 +55,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 76e6a8530b..5afedf4d05 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 1dc813d0a3..7a90237ba2 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -3,7 +3,7 @@
  */
 
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/ioctl.h>
@@ -52,7 +52,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -79,7 +79,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -89,7 +89,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -98,7 +98,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -112,7 +112,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -122,7 +122,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -503,7 +503,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 	ret = rte_ctrl_thread_create(&internal->tid, name, NULL, notify_relay,
 				     (void *)internal);
 	if (ret != 0) {
-		DRV_LOG(ERR, "failed to create notify relay pthread.");
+		DRV_LOG(ERR, "failed to create notify relay thread.");
 		return -1;
 	}
 
@@ -513,13 +513,11 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
-	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+	if (internal->tid.opaque_id) {
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
-	internal->tid = 0;
+	internal->tid.opaque_id = 0;
 
 	if (internal->epfd >= 0)
 		close(internal->epfd);
@@ -809,7 +807,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 	ret = rte_ctrl_thread_create(&internal->tid, name, NULL, vring_relay,
 				     (void *)internal);
 	if (ret != 0) {
-		DRV_LOG(ERR, "failed to create ring relay pthread.");
+		DRV_LOG(ERR, "failed to create ring relay thread.");
 		return -1;
 	}
 
@@ -819,13 +817,11 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
-	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+	if (internal->tid.opaque_id) {
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
-	internal->tid = 0;
+	internal->tid.opaque_id = 0;
 
 	if (internal->epfd >= 0)
 		close(internal->epfd);
@@ -1253,9 +1249,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1293,9 +1289,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index e5e03e6582..e7f4acb48d 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -736,10 +736,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -770,7 +770,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -779,7 +779,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -790,7 +790,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 		if (priv->vdev)
 			rte_vdpa_unregister_device(priv->vdev);
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index 722c72b65e..cf7df473f8 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,9 +119,9 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t no_traffic_counter;
-	pthread_t timer_tid;
+	rte_thread_t timer_tid;
 	int event_mode;
 	int event_core; /* Event thread cpu affinity core. */
 	uint32_t event_us;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 88f6a4256d..b3639659f6 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -285,7 +285,7 @@ mlx5_vdpa_event_handle(void *arg)
 	case MLX5_VDPA_EVENT_MODE_FIXED_TIMER:
 		priv->timer_delay_us = priv->event_us;
 		while (1) {
-			pthread_mutex_lock(&priv->vq_config_lock);
+			rte_thread_mutex_lock(&priv->vq_config_lock);
 			max = mlx5_vdpa_queues_complete(priv);
 			if (max == 0 && priv->no_traffic_counter++ >=
 			    priv->no_traffic_max) {
@@ -293,10 +293,10 @@ mlx5_vdpa_event_handle(void *arg)
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
 				do {
-					pthread_mutex_unlock
+					rte_thread_mutex_unlock
 							(&priv->vq_config_lock);
 					cq = mlx5_vdpa_event_wait(priv);
-					pthread_mutex_lock
+					rte_thread_mutex_lock
 							(&priv->vq_config_lock);
 					if (cq == NULL ||
 					       mlx5_vdpa_queue_complete(cq) > 0)
@@ -307,7 +307,7 @@ mlx5_vdpa_event_handle(void *arg)
 			} else if (max != 0) {
 				priv->no_traffic_counter = 0;
 			}
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			mlx5_vdpa_timer_sleep(priv, max);
 		}
 		return NULL;
@@ -315,10 +315,10 @@ mlx5_vdpa_event_handle(void *arg)
 		do {
 			cq = mlx5_vdpa_event_wait(priv);
 			if (cq != NULL) {
-				pthread_mutex_lock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->vq_config_lock);
 				if (mlx5_vdpa_queue_complete(cq) > 0)
 					mlx5_vdpa_cq_arm(priv, cq);
-				pthread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
 			}
 		} while (1);
 		return NULL;
@@ -340,7 +340,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -386,7 +386,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -473,27 +473,25 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
-	pthread_attr_init(&attr);
-	ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+
+	ret = rte_thread_attr_init(&attr);
 	if (ret) {
-		DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+		DRV_LOG(ERR, "Failed to initialize thread attributes");
 		return -1;
 	}
-	ret = pthread_attr_setschedparam(&attr, &sp);
+	ret = rte_thread_attr_set_priority(&attr,
+			RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to set thread priority.");
 		return -1;
 	}
-	ret = pthread_create(&priv->timer_tid, &attr, mlx5_vdpa_event_handle,
+	ret = rte_thread_create(&priv->timer_tid, &attr, mlx5_vdpa_event_handle,
 			     (void *)priv);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to create timer thread.");
@@ -504,13 +502,13 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 		CPU_SET(priv->event_core, &cpuset);
 	else
 		cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-	ret = pthread_setaffinity_np(priv->timer_tid, sizeof(cpuset), &cpuset);
+	ret = rte_thread_set_affinity_by_id(priv->timer_tid, &cpuset);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to set thread affinity.");
 		return -1;
 	}
 	snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
-	ret = rte_thread_setname(priv->timer_tid, name);
+	ret = pthread_setname_np(priv->timer_tid.opaque_id, name);
 	if (ret)
 		DRV_LOG(DEBUG, "Cannot set timer thread name.");
 	return 0;
@@ -519,13 +517,11 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 void
 mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
-	void *status;
-
-	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+	if (priv->timer_tid.opaque_id) {
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
-	priv->timer_tid = 0;
+	priv->timer_tid.opaque_id = 0;
 }
 
 void
diff --git a/examples/kni/main.c b/examples/kni/main.c
index beabb3c848..e4741f85ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/performance-thread/pthread_shim/main.c b/examples/performance-thread/pthread_shim/main.c
index 257de50692..bef7b59842 100644
--- a/examples/performance-thread/pthread_shim/main.c
+++ b/examples/performance-thread/pthread_shim/main.c
@@ -164,7 +164,7 @@ static void *initial_lthread(void *args __rte_unused)
 			rte_exit(EXIT_FAILURE, "Cannot create helloworld thread\n");
 
 		snprintf(name, sizeof(name), "helloworld-%u", (uint32_t)i);
-		rte_thread_setname(tid[i], name);
+		pthread_setname_np(tid[i], name);
 	}
 
 	/* wait for 1s to allow threads
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index d2179eadb9..4d02502602 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1634,7 +1634,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = RTE_VHOST_USER_NET_COMPLIANT_OL_FLAGS;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index fe2b4e4803..5b31d58ac2 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -5,7 +5,7 @@
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 #endif
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sched.h>
 
 #include <stdint.h>
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features, protocol_features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring, inflight_shmfd;
 
@@ -693,7 +693,7 @@ new_device(int vid)
 
 	/* device has been started */
 	ctrlr->started = 1;
-	pthread_detach(tid);
+	rte_thread_detach(tid);
 	return 0;
 }
 
diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index 9d29696b84..1f6aba498c 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -1872,8 +1872,7 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1901,8 +1900,7 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/eal/common/eal_common_proc.c b/lib/eal/common/eal_common_proc.c
index dc4a2efa82..e8a93ee829 100644
--- a/lib/eal/common/eal_common_proc.c
+++ b/lib/eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -524,9 +524,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -584,7 +584,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -998,9 +998,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1021,7 +1021,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1040,7 +1040,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1118,7 +1118,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1141,7 +1141,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1185,7 +1185,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1201,7 +1201,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/eal/common/eal_common_thread.c b/lib/eal/common/eal_common_thread.c
index 1a52f42a2b..d46ab8cf77 100644
--- a/lib/eal/common/eal_common_thread.c
+++ b/lib/eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,8 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,14 +167,14 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 	unsigned int refcnt;
 };
 
 static void ctrl_params_free(struct rte_thread_ctrl_params *params)
 {
 	if (__atomic_sub_fetch(&params->refcnt, 1, __ATOMIC_ACQ_REL) == 0) {
-		(void)pthread_barrier_destroy(&params->configured);
+		(void)rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 }
@@ -192,7 +190,7 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	pthread_barrier_wait(&params->configured);
+	rte_thread_barrier_wait(&params->configured);
 	start_routine = params->start_routine;
 	ctrl_params_free(params);
 
@@ -203,8 +201,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -221,11 +219,11 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->arg = arg;
 	params->refcnt = 2;
 
-	ret = pthread_barrier_init(&params->configured, NULL, 2);
+	ret = rte_thread_barrier_init(&params->configured, 2);
 	if (ret != 0)
 		goto fail_no_barrier;
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, (void *)params);
 	if (ret != 0)
 		goto fail_with_barrier;
 
@@ -236,22 +234,22 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, cpuset);
 	if (ret != 0)
 		params->start_routine = NULL;
 
-	pthread_barrier_wait(&params->configured);
+	rte_thread_barrier_wait(&params->configured);
 	ctrl_params_free(params);
 
 	if (ret != 0)
 		/* start_routine has been set to NULL above; */
 		/* ctrl thread will exit immediately */
-		pthread_join(*thread, NULL);
+		rte_thread_join(*thread, NULL);
 
 	return -ret;
 
 fail_with_barrier:
-	(void)pthread_barrier_destroy(&params->configured);
+	(void)rte_thread_barrier_destroy(&params->configured);
 
 fail_no_barrier:
 	free(params);
@@ -276,8 +274,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
-			&cpuset) != 0)
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
 	if (lcore_id >= RTE_MAX_LCORE)
@@ -304,3 +301,14 @@ rte_thread_unregister(void)
 		RTE_LOG(DEBUG, EAL, "Unregistered non-EAL thread (was lcore %u).\n",
 			lcore_id);
 }
+
+void rte_thread_priority_init(void)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+
+	/* If the user doesn't specify the priority through the command
+	 * line arguments, the default 'normal' value will be used.
+	 */
+	internal_conf->thread_priority = RTE_THREAD_PRIORITY_NORMAL;
+}
diff --git a/lib/eal/common/eal_common_trace.c b/lib/eal/common/eal_common_trace.c
index 24e27387b1..6df4a01277 100644
--- a/lib/eal/common/eal_common_trace.c
+++ b/lib/eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/eal/common/eal_private.h b/lib/eal/common/eal_private.h
index 64cf4e81c8..4b95001d7d 100644
--- a/lib/eal/common/eal_private.h
+++ b/lib/eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/eal/common/eal_thread.h b/lib/eal/common/eal_thread.h
index 4a49117be8..7b3b884463 100644
--- a/lib/eal/common/eal_thread.h
+++ b/lib/eal/common/eal_thread.h
@@ -58,4 +58,10 @@ eal_thread_dump_affinity(rte_cpuset_t *cpuset, char *str, unsigned int size);
 int
 eal_thread_dump_current_affinity(char *str, unsigned int size);
 
+/**
+ * Set the initial thread priority in the internal configuration
+ * to the default value of RTE_THREAD_PRIORITY_NORMAL.
+ */
+void rte_thread_priority_init(void);
+
 #endif /* EAL_THREAD_H */
diff --git a/lib/eal/common/malloc_mp.c b/lib/eal/common/malloc_mp.c
index 2e597a17a2..2620b00e62 100644
--- a/lib/eal/common/malloc_mp.c
+++ b/lib/eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -301,7 +301,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -387,10 +387,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -409,7 +409,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -539,10 +539,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -557,7 +557,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -588,10 +588,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -603,7 +603,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -616,7 +616,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -706,7 +706,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -767,10 +767,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/freebsd/eal.c b/lib/eal/freebsd/eal.c
index f4d1676754..ec7fd57e7d 100644
--- a/lib/eal/freebsd/eal.c
+++ b/lib/eal/freebsd/eal.c
@@ -667,7 +667,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -676,6 +676,8 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	rte_thread_priority_init();
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -690,7 +692,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -854,7 +856,14 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,10 +874,25 @@ rte_eal_init(int argc, char **argv)
 
 	ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
 
-	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (tid=%p;cpuset=[%s%s])\n",
-		config->main_lcore, thread_id, cpuset,
+	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (cpuset=[%s%s])\n",
+		config->main_lcore, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -882,8 +906,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -893,10 +919,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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/eal/freebsd/eal_alarm.c b/lib/eal/freebsd/eal_alarm.c
index c38b2e04f8..e5d7b130b1 100644
--- a/lib/eal/freebsd/eal_alarm.c
+++ b/lib/eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/eal/freebsd/eal_interrupts.c b/lib/eal/freebsd/eal_interrupts.c
index 86810845fe..c0bf6c882a 100644
--- a/lib/eal/freebsd/eal_interrupts.c
+++ b/lib/eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -737,5 +737,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/eal/freebsd/eal_thread.c b/lib/eal/freebsd/eal_thread.c
index 1dce9b04f2..cb8563cb7a 100644
--- a/lib/eal/freebsd/eal_thread.c
+++ b/lib/eal/freebsd/eal_thread.c
@@ -73,15 +73,15 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id, lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -93,8 +93,8 @@ eal_thread_loop(__rte_unused void *arg)
 	__rte_thread_init(lcore_id, &lcore_config[lcore_id].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 ? "" : "...");
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (cpuset=[%s%s])\n",
+		lcore_id, cpuset, ret == 0 ? "" : "...");
 
 	rte_eal_trace_thread_lcore_ready(lcore_id, cpuset);
 
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index 88a9eba12f..3b872f228f 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
         'rte_string_fns.h',
         'rte_tailq.h',
         'rte_thread.h',
+        'rte_thread_types.h',
         'rte_time.h',
         'rte_trace.h',
         'rte_trace_point.h',
diff --git a/lib/eal/include/rte_lcore.h b/lib/eal/include/rte_lcore.h
index 1550b75da0..d5e004105d 100644
--- a/lib/eal/include/rte_lcore.h
+++ b/lib/eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/eal/include/rte_per_lcore.h b/lib/eal/include/rte_per_lcore.h
index eaedf0cb37..025d97f962 100644
--- a/lib/eal/include/rte_per_lcore.h
+++ b/lib/eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c
index ba19fc6347..70357e099a 100644
--- a/lib/eal/linux/eal.c
+++ b/lib/eal/linux/eal.c
@@ -963,7 +963,6 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -975,6 +974,8 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	rte_thread_priority_init();
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -991,7 +992,6 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1219,7 +1219,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1229,10 +1237,27 @@ rte_eal_init(int argc, char **argv)
 		&lcore_config[config->main_lcore].cpuset);
 
 	ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
-	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (tid=%zx;cpuset=[%s%s])\n",
-		config->main_lcore, (uintptr_t)thread_id, cpuset,
+	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (cpuset=[%s%s])\n",
+		config->main_lcore, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1246,9 +1271,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1260,11 +1287,6 @@ 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/eal/linux/eal_alarm.c b/lib/eal/linux/eal_alarm.c
index 3252c6fa59..fef22a347c 100644
--- a/lib/eal/linux/eal_alarm.c
+++ b/lib/eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/eal/linux/eal_interrupts.c b/lib/eal/linux/eal_interrupts.c
index 22b3b7bcd9..e106fa186c 100644
--- a/lib/eal/linux/eal_interrupts.c
+++ b/lib/eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1570,5 +1570,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/eal/linux/eal_thread.c b/lib/eal/linux/eal_thread.c
index 83c2034b93..fe6b02788f 100644
--- a/lib/eal/linux/eal_thread.c
+++ b/lib/eal/linux/eal_thread.c
@@ -73,15 +73,15 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id,lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -93,8 +93,8 @@ eal_thread_loop(__rte_unused void *arg)
 	__rte_thread_init(lcore_id, &lcore_config[lcore_id].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 ? "" : "...");
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (cpuset=[%s%s])\n",
+		lcore_id, cpuset, ret == 0 ? "" : "...");
 
 	rte_eal_trace_thread_lcore_ready(lcore_id, cpuset);
 
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -156,7 +156,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	char truncated[16];
 
 	strlcpy(truncated, name, sizeof(truncated));
-	ret = pthread_setname_np(id, truncated);
+	ret = pthread_setname_np(id.opaque_id, truncated);
 #endif
 #endif
 	RTE_SET_USED(id);
@@ -164,12 +164,12 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
 #if __GLIBC_PREREQ(2, 12)
-	ret = pthread_getname_np(id, name, len);
+	ret = pthread_getname_np(id.opaque_id, name, len);
 #endif
 #endif
 	RTE_SET_USED(id);
diff --git a/lib/eal/linux/eal_timer.c b/lib/eal/linux/eal_timer.c
index 7cf15cabac..b4099a0aa2 100644
--- a/lib/eal/linux/eal_timer.c
+++ b/lib/eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index dc711b4240..f2b8063760 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
         'eal_file.c',
         'eal_unix_memory.c',
         'eal_unix_timer.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c
deleted file mode 100644
index c72d619ec1..0000000000
--- a/lib/eal/unix/rte_thread.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_key_delete(rte_thread_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_value_set(rte_thread_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_value_get(rte_thread_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/eal/version.map b/lib/eal/version.map
index fe5c3dac98..3126c77e4d 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,28 @@ EXPERIMENTAL {
 	rte_version_release; # WINDOWS_NO_EXPORT
 	rte_version_suffix; # WINDOWS_NO_EXPORT
 	rte_version_year; # WINDOWS_NO_EXPORT
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel; # WINDOWS_NO_EXPORT
+	rte_thread_detach;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c
index 28c787c0b0..3e0834a24a 100644
--- a/lib/eal/windows/eal.c
+++ b/lib/eal/windows/eal.c
@@ -274,6 +274,8 @@ rte_eal_init(int argc, char **argv)
 		eal_get_internal_configuration();
 	int ret;
 
+	rte_thread_priority_init();
+
 	eal_log_init(NULL, 0);
 
 	eal_log_level_parse(argc, argv);
@@ -375,6 +377,36 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			&lcore_config[config->main_lcore].cpuset) != 0) {
+		rte_eal_init_alert("Cannot set affinity");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -390,8 +422,17 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		ret = rte_thread_attr_set_affinity(&thread_attr, &lcore_config[i].cpuset);
+		if (ret != 0) {
+			rte_eal_init_alert("Cannot set thread affinity attribute");
+			rte_errno = ret;
+			return -1;
+		}
+
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/eal/windows/eal_interrupts.c b/lib/eal/windows/eal_interrupts.c
index 1d4cf794df..a529ef95e3 100644
--- a/lib/eal/windows/eal_interrupts.c
+++ b/lib/eal/windows/eal_interrupts.c
@@ -2,12 +2,14 @@
  * Copyright 2020 Mellanox Technologies, Ltd
  */
 
+#include <inttypes.h>
+
 #include <rte_interrupts.h>
 
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +78,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -92,9 +94,9 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 {
 	HANDLE handle;
 
-	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
+	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread.opaque_id);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread (%" PRIuPTR ")", intr_thread.opaque_id);
 		return -ENOENT;
 	}
 
diff --git a/lib/eal/windows/eal_thread.c b/lib/eal/windows/eal_thread.c
index 9c3f6d69fd..0c6bca24cf 100644
--- a/lib/eal/windows/eal_thread.c
+++ b/lib/eal/windows/eal_thread.c
@@ -60,15 +60,15 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id, lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -80,7 +80,7 @@ eal_thread_loop(void *arg __rte_unused)
 	__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);
+		lcore_id, thread_id.opaque_id, cpuset);
 
 	/* read on our pipe to get commands */
 	while (1) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index dc5dc8240a..4b92b198c7 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/eal/windows/include/meson.build b/lib/eal/windows/include/meson.build
index b3534b025f..7d9b3393e4 100644
--- a/lib/eal/windows/include/meson.build
+++ b/lib/eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/eal/windows/include/pthread.h b/lib/eal/windows/include/pthread.h
deleted file mode 100644
index 27fd2cca52..0000000000
--- a/lib/eal/windows/include/pthread.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	!InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	!DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) !TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_detach(__rte_unused pthread_t thread)
-{
-	return 0;
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/meson.build b/lib/eal/windows/meson.build
index ff9cbec417..4b7db4754b 100644
--- a/lib/eal/windows/meson.build
+++ b/lib/eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
         'eal_timer.c',
         'fnmatch.c',
         'getopt.c',
-        'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'eal/common/rte_thread.c'
+else
+	sources += 'eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index c607eabb5b..bc0a4c973a 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -526,7 +526,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -600,7 +600,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/ethdev/rte_ethdev_core.h b/lib/ethdev/rte_ethdev_core.h
index 4679d948fa..ad1053b561 100644
--- a/lib/ethdev/rte_ethdev_core.h
+++ b/lib/ethdev/rte_ethdev_core.h
@@ -5,7 +5,8 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
+#include <rte_thread.h>
+#include <sys/types.h>
 
 /**
  * @file
@@ -182,7 +183,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 8cb7a069c8..4f112d1af7 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -226,14 +226,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/eventdev/rte_event_eth_rx_adapter.c b/lib/eventdev/rte_event_eth_rx_adapter.c
index 13dfb28401..be39cf9089 100644
--- a/lib/eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/eventdev/rte_event_eth_rx_adapter.c
@@ -147,7 +147,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1449,12 +1449,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c
index 55d4856f9e..b97774ccd4 100644
--- a/lib/vhost/fd_man.c
+++ b/lib/vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/vhost/fd_man.h b/lib/vhost/fd_man.h
index 3ab5cfdd60..ba58d849e8 100644
--- a/lib/vhost/fd_man.h
+++ b/lib/vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
index 5d0d728d52..36a430ae25 100644
--- a/lib/vhost/socket.c
+++ b/lib/vhost/socket.c
@@ -14,7 +14,7 @@
 #include <sys/queue.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_log.h>
 
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -74,7 +74,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -87,12 +87,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -271,9 +271,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -326,9 +326,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -420,11 +420,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -456,7 +456,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -487,7 +487,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -499,7 +499,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -510,7 +510,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -554,9 +554,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -588,11 +588,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -602,11 +602,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -617,11 +617,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -631,7 +631,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -641,7 +641,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -651,7 +651,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -659,12 +659,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -674,7 +674,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -685,7 +685,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -698,7 +698,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -724,7 +724,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -734,11 +734,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -751,7 +751,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -779,7 +779,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -791,7 +791,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -817,7 +817,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -849,7 +849,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -869,7 +869,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -951,7 +951,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
-		if (vsocket->reconnect && reconn_tid == 0) {
+		if (vsocket->reconnect && reconn_tid.opaque_id == 0) {
 			if (vhost_user_reconnect_init() != 0)
 				goto out_mutex;
 		}
@@ -965,18 +965,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -987,7 +987,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -1001,7 +1001,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1019,13 +1019,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1039,9 +1039,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1053,7 +1054,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1063,7 +1064,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1073,18 +1075,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1098,11 +1100,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1112,9 +1114,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1123,16 +1125,16 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
 
-	if (fdset_tid == 0) {
+	if (fdset_tid.opaque_id == 0) {
 		/**
 		 * create a pipe which will be waited by poll and notified to
 		 * rebuild the wait list of poll.
diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c
index c96f6335c8..ee7470bf8b 100644
--- a/lib/vhost/vhost.c
+++ b/lib/vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -657,7 +657,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -666,7 +666,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -674,12 +674,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 56bdfd0f0a..46d156cf2f 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -42,5 +42,7 @@ option('enable_trace_fp', type: 'boolean', value: false, description:
        'enable fast path trace points.')
 option('tests', type: 'boolean', value: true, description:
        'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false, description:
        'use HPET timer in EAL')
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading
  2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                         ` (9 preceding siblings ...)
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                       ` Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
                                           ` (10 more replies)
  10 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model, so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread_types.h (librte_eal/include)
* rte_thread_windows_types.h (librte_eal/windows/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

For flexibility, the user is offered the option of either using the RTE_THREAD_* API or
a 3rd party thread library, through a meson flag “use_external_thread_lib”.
By default, this flag is set to FALSE, which means Windows libraries and applications
will use the RTE_THREAD_* API for managing threads.

If compiling on Windows and the “use_external_thread_lib” is *not* set,
the following files will be parsed: 
* include/rte_thread.h
* windows/include/rte_thread_windows_types.h
* windows/rte_thread.c
In all other cases, the compilation/parsing includes the following files:
* include/rte_thread.h 
* include/rte_thread_types.h
* common/rte_thread.c

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}

lib/librte_eal/windows/meson.build
if get_option('use_external_thread_lib')
	sources += 'librte_eal/common/rte_thread.c'
else
	sources += 'librte_eal/windows/rte_thread.c'
endif
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
Note that this patchset was focused on introducing new API that will
remove the Windows pthread.h shim. In DPDK, there are still a few references
to pthread_* that were not implemented in the shim.
The long term plan is for EAL to provide full threading support:
* Adding support for conditional variables
* Additional functionality offered by pthread_* (such as pthread_setname_np, etc.)
* Static mutex initializers are not used on Windows. If we must continue
  using them, they need to be platform dependent and an implementation will
  need to be provided for Windows.

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (10):
  eal: add thread id and simple thread functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Enable the new EAL thread API

 app/test/process.h                            |   8 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   5 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/dpaa/dpaa_bus.c                   |  14 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  19 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   4 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   2 +-
 drivers/net/ark/ark_pktgen.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  26 +-
 drivers/net/axgbe/axgbe_common.h              |   2 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 +-
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |  12 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   6 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   8 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  24 +-
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +-
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   6 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  46 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +-
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   4 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  46 +-
 examples/kni/main.c                           |   6 +-
 .../performance-thread/pthread_shim/main.c    |   2 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  12 +-
 lib/eal/common/eal_common_options.c           |  34 +-
 lib/eal/common/eal_common_proc.c              |  48 +-
 lib/eal/common/eal_common_thread.c            |  42 +-
 lib/eal/common/eal_common_trace.c             |   2 +-
 lib/eal/common/eal_internal_cfg.h             |   2 +
 lib/eal/common/eal_options.h                  |   2 +
 lib/eal/common/eal_private.h                  |   2 +-
 lib/eal/common/eal_thread.h                   |   6 +
 lib/eal/common/malloc_mp.c                    |  32 +-
 lib/eal/common/meson.build                    |   1 +
 lib/eal/common/rte_thread.c                   | 422 +++++++++++
 lib/eal/freebsd/eal.c                         |  42 +-
 lib/eal/freebsd/eal_alarm.c                   |  12 +-
 lib/eal/freebsd/eal_interrupts.c              |   4 +-
 lib/eal/freebsd/eal_thread.c                  |  14 +-
 lib/eal/include/meson.build                   |   1 +
 lib/eal/include/rte_lcore.h                   |   8 +-
 lib/eal/include/rte_per_lcore.h               |   2 -
 lib/eal/include/rte_thread.h                  | 378 +++++++++-
 lib/eal/include/rte_thread_types.h            |  14 +
 lib/eal/linux/eal.c                           |  46 +-
 lib/eal/linux/eal_alarm.c                     |  10 +-
 lib/eal/linux/eal_interrupts.c                |   4 +-
 lib/eal/linux/eal_thread.c                    |  18 +-
 lib/eal/linux/eal_timer.c                     |   2 +-
 lib/eal/unix/meson.build                      |   1 -
 lib/eal/unix/rte_thread.c                     |  92 ---
 lib/eal/version.map                           |  22 +
 lib/eal/windows/eal.c                         |  43 +-
 lib/eal/windows/eal_interrupts.c              |  10 +-
 lib/eal/windows/eal_lcore.c                   | 169 +++--
 lib/eal/windows/eal_thread.c                  |  28 +-
 lib/eal/windows/eal_windows.h                 |  20 +-
 lib/eal/windows/include/meson.build           |   1 +
 lib/eal/windows/include/pthread.h             | 192 -----
 .../include/rte_windows_thread_types.h        |  19 +
 lib/eal/windows/include/sched.h               |   2 +-
 lib/eal/windows/meson.build                   |   7 +-
 lib/eal/windows/rte_thread.c                  | 678 +++++++++++++++++-
 lib/ethdev/rte_ethdev.c                       |   4 +-
 lib/ethdev/rte_ethdev_core.h                  |   5 +-
 lib/ethdev/rte_flow.c                         |   4 +-
 lib/eventdev/rte_event_eth_rx_adapter.c       |   6 +-
 lib/vhost/fd_man.c                            |  40 +-
 lib/vhost/fd_man.h                            |   6 +-
 lib/vhost/socket.c                            | 130 ++--
 lib/vhost/vhost.c                             |  10 +-
 meson_options.txt                             |   2 +
 108 files changed, 2345 insertions(+), 967 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 create mode 100644 lib/eal/include/rte_thread_types.h
 delete mode 100644 lib/eal/unix/rte_thread.c
 delete mode 100644 lib/eal/windows/include/pthread.h
 create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08 23:03                           ` Dmitry Kozlyuk
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                           ` (9 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c                   | 105 ++++++++++++++++++
 lib/eal/include/rte_thread.h                  |  53 +++++++--
 lib/eal/include/rte_thread_types.h            |  10 ++
 .../include/rte_windows_thread_types.h        |  10 ++
 lib/eal/windows/rte_thread.c                  |  17 +++
 5 files changed, 186 insertions(+), 9 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 create mode 100644 lib/eal/include/rte_thread_types.h
 create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
new file mode 100644
index 0000000000..1292f7a8f8
--- /dev/null
+++ b/lib/eal/common/rte_thread.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_thread.h>
+
+struct eal_tls_key {
+	pthread_key_t thread_index;
+};
+
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id = { 0 };
+
+	thread_id.opaque_id = pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal(t1.opaque_id, t2.opaque_id);
+}
+
+int
+rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
+{
+	int err;
+	rte_thread_key k;
+
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
+		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
+			 strerror(err));
+		free(k);
+		return err;
+	}
+	*key = k;
+	return 0;
+}
+
+int
+rte_thread_key_delete(rte_thread_key key)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_key_delete(key->thread_index);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
+			 strerror(err));
+		free(key);
+		return err;
+	}
+	free(key);
+	return 0;
+}
+
+int
+rte_thread_value_set(rte_thread_key key, const void *value)
+{
+	int err;
+
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		return EINVAL;
+	}
+	err = pthread_setspecific(key->thread_index, value);
+	if (err != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
+			strerror(err));
+		return err;
+	}
+	return 0;
+}
+
+void *
+rte_thread_value_get(rte_thread_key key)
+{
+	if (key == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
+		rte_errno = EINVAL;
+		return NULL;
+	}
+	return pthread_getspecific(key->thread_index);
+}
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..347df1a6ae 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,50 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+#if defined(RTE_USE_WINDOWS_THREAD_TYPES)
+#include <rte_windows_thread_types.h>
+#else
+#include <rte_thread_types.h>
+#endif
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +104,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +119,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +134,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
new file mode 100644
index 0000000000..d67b24a563
--- /dev/null
+++ b/lib/eal/include/rte_thread_types.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <pthread.h>
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
new file mode 100644
index 0000000000..60e6d94553
--- /dev/null
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+
+#ifndef _RTE_THREAD_TYPES_H_
+#define _RTE_THREAD_TYPES_H_
+
+#include <rte_windows.h>
+
+#endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..3f3ebba21f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id = { 0 };
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 02/10] eal: add thread attributes
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08 23:03                           ` Dmitry Kozlyuk
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                           ` (8 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the already known “rte_cpuset_t” type.

An rte_thread_attr_t object can be set to the default values
by calling *rte_thread_attr_init()*.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c                   | 51 +++++++++++
 lib/eal/include/rte_thread.h                  | 89 +++++++++++++++++++
 lib/eal/include/rte_thread_types.h            |  3 +
 .../include/rte_windows_thread_types.h        |  3 +
 lib/eal/windows/rte_thread.c                  | 53 +++++++++++
 5 files changed, 199 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 1292f7a8f8..4b1e8f995e 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,56 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1.opaque_id, t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_ASSERT(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL || cpuset == NULL) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if ((thread_attr == NULL) || (cpuset == NULL)) {
+		RTE_LOG(DEBUG, EAL, "Invalid thread attributes parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+			"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 347df1a6ae..eff00023d7 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -36,6 +36,26 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -66,6 +86,75 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index d67b24a563..996232c636 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,4 +7,7 @@
 
 #include <pthread.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL               0
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 60e6d94553..5bdeaad3d4 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,4 +7,7 @@
 
 #include <rte_windows.h>
 
+#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
+#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 3f3ebba21f..cc319d3628 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -5,6 +5,7 @@
 
 #include <rte_common.h>
 #include <rte_errno.h>
+#include <rte_debug.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
 
@@ -28,6 +29,58 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_ASSERT(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->cpuset = *cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set affinity attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	*cpuset = thread_attr->cpuset;
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	if (thread_attr == NULL) {
+		RTE_LOG(DEBUG, EAL,
+		"Unable to set priority attribute, invalid parameter\n");
+		return EINVAL;
+	}
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 03/10] eal/windows: translate Windows errors to errno-style errors
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                           ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 90 +++++++++++++++++++++++++++---------
 2 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index eff00023d7..f3eeb28753 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -236,9 +236,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index cc319d3628..6ea1dc2a05 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char* message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -85,18 +133,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -104,16 +152,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -122,19 +170,17 @@ rte_thread_key_delete(rte_thread_key key)
 int
 rte_thread_value_set(rte_thread_key key, const void *value)
 {
+	int ret;
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -143,16 +189,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (2 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08 23:03                           ` Dmitry Kozlyuk
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                           ` (6 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  14 +++
 lib/eal/include/rte_thread.h  |  36 ++++++++
 lib/eal/windows/eal_lcore.c   | 169 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 127 ++++++++++++++++++++++++-
 5 files changed, 310 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 4b1e8f995e..ceb27feaa7 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,20 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal(t1.opaque_id, t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index f3eeb28753..1f02962146 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -86,6 +86,42 @@ rte_thread_t rte_thread_self(void);
 __rte_experimental
 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..519a62b96d 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,111 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	DWORD infos_size = 0;
+	int ret = 0;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	cpu_map.cpu_count = 0;
+	USHORT group_count = infos->Group.ActiveGroupCount;
+	for (USHORT group_number = 0; group_number < group_count; group_number++) {
+		KAFFINITY affinity = infos->Group.GroupInfo[group_number].ActiveProcessorMask;
+
+		for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[cpu_map.cpu_count].Group = group_number;
+			cpu_map.cpus[cpu_map.cpu_count].Mask = (KAFFINITY)1 << i;
+			cpu_map.cpu_count++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (unsigned int i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +177,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +209,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +235,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 478accc1b9..dc5dc8240a 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 6ea1dc2a05..9e74a538c2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_errno.h>
 #include <rte_debug.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,130 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+			       PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	if (cpuset == NULL) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	int ret = 0;
+
+	if (cpuset == NULL) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 05/10] eal: implement thread priority management functions
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (3 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08 23:04                           ` Dmitry Kozlyuk
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                           ` (5 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c                   | 51 ++++++++++
 lib/eal/include/rte_thread.h                  | 17 ++++
 lib/eal/include/rte_thread_types.h            |  3 -
 .../include/rte_windows_thread_types.h        |  3 -
 lib/eal/windows/rte_thread.c                  | 92 +++++++++++++++++++
 5 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ceb27feaa7..5cee19bb7d 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -48,6 +48,57 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return pthread_getaffinity_np(thread_id.opaque_id, sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri, int *pol)
+{
+	RTE_VERIFY(os_pri != NULL);
+	RTE_VERIFY(pol != NULL);
+
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri)
+	{
+		case RTE_THREAD_PRIORITY_NORMAL:
+			*pol = SCHED_OTHER;
+
+			/*
+			 * Choose the middle of the range to represent
+			 * the priority 'normal'.
+			 * On Linux, this should be 0, since both
+			 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+			 */
+			*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2;
+			break;
+		case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+			*pol = SCHED_RR;
+			*os_pri = sched_get_priority_max(SCHED_RR);
+			break;
+		default:
+			RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+			return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority, &policy);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return pthread_setschedparam(thread_id.opaque_id, policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 1f02962146..5c54cd9d67 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -122,6 +122,23 @@ __rte_experimental
 int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		rte_cpuset_t *cpuset);
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+			    enum rte_thread_priority priority);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index 996232c636..d67b24a563 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,7 +7,4 @@
 
 #include <pthread.h>
 
-#define EAL_THREAD_PRIORITY_NORMAL               0
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
-
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 5bdeaad3d4..60e6d94553 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,7 +7,4 @@
 
 #include <rte_windows.h>
 
-#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
-#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
-
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 9e74a538c2..6dc3d575c0 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -202,6 +202,98 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static HANDLE
+get_process_handle_from_thread_handle(HANDLE thread_handle)
+{
+	DWORD process_id = 0;
+
+	process_id = GetProcessIdOfThread(thread_handle);
+	if (process_id == 0) {
+		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
+		return NULL;
+	}
+
+	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
+}
+
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	RTE_VERIFY(os_pri != NULL);
+	RTE_VERIFY(pri_class != NULL);
+
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri)
+	{
+		case RTE_THREAD_PRIORITY_NORMAL:
+			*pri_class = NORMAL_PRIORITY_CLASS;
+			*os_pri = THREAD_PRIORITY_NORMAL;
+			break;
+		case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+			*pri_class = REALTIME_PRIORITY_CLASS;
+			*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+			break;
+		default:
+			RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+			return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle = NULL;
+	HANDLE process_handle = NULL;
+	int priority_class = NORMAL_PRIORITY_CLASS;
+	int os_priority = THREAD_PRIORITY_NORMAL;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+				   THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority, &priority_class);
+	if (ret != 0) {
+		return ret;
+	}
+	process_handle = get_process_handle_from_thread_handle(thread_handle);
+	if (process_handle == NULL) {
+		ret = thread_log_last_error("OpenProcess()");
+		goto cleanup;
+	}
+
+	if (!SetPriorityClass(process_handle, priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	if (process_handle != NULL) {
+		CloseHandle(process_handle);
+		process_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (4 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08 23:04                           ` Dmitry Kozlyuk
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                           ` (4 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for thread creation, join, canceling, detaching.

The *rte_thread_create()* function can optionally receive an rte_thread_attr_t
object that will cause the thread to be created with the affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 116 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  67 +++++++++++++++
 lib/eal/windows/rte_thread.c | 162 +++++++++++++++++++++++++++++++++++
 3 files changed, 345 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 5cee19bb7d..84050d0f4c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -149,6 +149,122 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+						   PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		/*
+		 * In case a realtime scheduling policy is requested,
+		 * the sched_priority parameter is set to the value stored in
+		 * thread_attr. Otherwise, for the default scheduling policy
+		 * (SCHED_OTHER) sched_priority needs to be initialized to 0.
+		 */
+		if (thread_attr->priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			policy = SCHED_RR;
+			param.sched_priority = thread_attr->priority;
+		}
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setaffinity_np(attrp,
+						  sizeof(thread_attr->cpuset),
+						  &thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create(&thread_id->opaque_id, attrp, thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join(thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(int *)(*pres);
+
+	return 0;
+}
+
+int rte_thread_cancel(rte_thread_t thread_id)
+{
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	return pthread_cancel(thread_id.opaque_id);
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach(thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5c54cd9d67..1d481b9ad5 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -208,6 +208,73 @@ __rte_experimental
 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 		enum rte_thread_priority priority);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		      const rte_thread_attr_t *thread_attr,
+		      void *(*thread_func)(void *), void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
+
+/**
+ * Terminates a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_cancel(rte_thread_t thread_id);
+
+/**
+ * Detaches a thread.
+ *
+ * @param thread_id
+ *    The id of the thread to be cancelled.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
+
 #ifdef RTE_HAS_CPUSET
 
 /**
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 6dc3d575c0..5afdd54e15 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	void* (*start_routine) (void*);
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -346,6 +351,163 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	intptr_t func_ret = 0;
+	struct thread_routine_ctx ctx = { NULL, NULL };
+
+	ctx.start_routine = pctx->start_routine;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (intptr_t)ctx.start_routine(ctx.routine_args);
+	return (DWORD)func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  void *(*thread_func)(void *), void *args)
+{
+	int ret = 0;
+	DWORD tid = 0;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->start_routine = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(&thread_attr->cpuset, &thread_affinity);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id, thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, int *value_ptr)
+{
+	HANDLE thread_handle = NULL;
+	DWORD result = 0;
+	DWORD exit_code = 0;
+	BOOL err = 0;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_cancel(rte_thread_t thread_id)
+{
+	int ret = 0;
+	HANDLE thread_handle = NULL;
+
+	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/*
+	 * TODO: Behavior is different between POSIX and Windows threads.
+	 * POSIX threads wait for a cancellation point.
+	 * Current Windows emulation kills thread at any point.
+	 */
+	ret = TerminateThread(thread_handle, 0);
+	if (ret != 0) {
+		ret = thread_log_last_error("TerminateThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	(void)thread_id;
+	return ENOTSUP;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (5 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08 23:04                           ` Dmitry Kozlyuk
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                           ` (3 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

On Linux, static initialization of a mutex is possible
through PTHREAD_MUTEX_INITIALIZER.

Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

To simulate static initialization, a fake initializator has been added:
The rte_mutex_lock() function will verify if the mutex has been initialized
using this fake initializer and if so, it will perform additional
initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c                   | 24 ++++++
 lib/eal/include/rte_thread.h                  | 53 ++++++++++++
 lib/eal/include/rte_thread_types.h            |  4 +
 .../include/rte_windows_thread_types.h        |  9 ++
 lib/eal/windows/rte_thread.c                  | 83 ++++++++++++++++++-
 5 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 84050d0f4c..4d7d9242a9 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -249,6 +249,30 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_lock(mutex);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_unlock(mutex);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	return pthread_mutex_destroy(mutex);
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 1d481b9ad5..db8ef20930 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -248,6 +248,58 @@ int rte_thread_create(rte_thread_t *thread_id,
 __rte_experimental
 int rte_thread_join(rte_thread_t thread_id, int *value_ptr);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex_t *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex_t *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
+
 /**
  * Terminates a thread.
  *
@@ -283,6 +335,7 @@ int rte_thread_detach(rte_thread_t thread_id);
  *
  * @param cpusetp
  *   Pointer to CPU affinity to set.
+ *
  * @return
  *   On success, return 0; otherwise return -1;
  */
diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
index d67b24a563..7bb0d2948c 100644
--- a/lib/eal/include/rte_thread_types.h
+++ b/lib/eal/include/rte_thread_types.h
@@ -7,4 +7,8 @@
 
 #include <pthread.h>
 
+#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
+
+typedef pthread_mutex_t                 rte_thread_mutex_t;
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
index 60e6d94553..c6c8502bfb 100644
--- a/lib/eal/windows/include/rte_windows_thread_types.h
+++ b/lib/eal/windows/include/rte_windows_thread_types.h
@@ -7,4 +7,13 @@
 
 #include <rte_windows.h>
 
+#define WINDOWS_MUTEX_INITIALIZER               (void*)-1
+#define RTE_THREAD_MUTEX_INITIALIZER            {WINDOWS_MUTEX_INITIALIZER}
+
+struct thread_mutex_t {
+	void* mutex_id;
+};
+
+typedef struct thread_mutex_t rte_thread_mutex_t;
+
 #endif /* _RTE_THREAD_TYPES_H_ */
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5afdd54e15..239aa6be5d 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -470,6 +470,88 @@ rte_thread_join(rte_thread_t thread_id, int *value_ptr)
 	return ret;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex_t *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex_t *mutex)
+{
+	int ret = 0;
+	void* id = 0;
+	rte_thread_mutex_t m;
+
+	RTE_VERIFY(mutex != NULL);
+
+	/* Check if mutex has been statically initialized */
+	id = InterlockedCompareExchangePointer(&mutex->mutex_id, mutex->mutex_id, WINDOWS_MUTEX_INITIALIZER);
+	/* If mutex has been statically initialized */
+	if (id == WINDOWS_MUTEX_INITIALIZER) {
+		ret = rte_thread_mutex_init(&m);
+		if (ret != 0) {
+			return ret;
+		}
+
+		id = InterlockedCompareExchangePointer(&mutex->mutex_id, m.mutex_id, WINDOWS_MUTEX_INITIALIZER);
+		/* If meanwhile the mutex was initialized by a different thread,
+		 * destroy the local initialization.
+		 */
+		if (id != WINDOWS_MUTEX_INITIALIZER) {
+			rte_thread_mutex_destroy(&m);
+		}
+	}
+
+	EnterCriticalSection(mutex->mutex_id);
+
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex_t *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (mutex->mutex_id == WINDOWS_MUTEX_INITIALIZER) {
+		goto cleanup;
+	}
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+
+cleanup:
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
@@ -549,7 +631,6 @@ rte_thread_key_delete(rte_thread_key key)
 int
 rte_thread_value_set(rte_thread_key key, const void *value)
 {
-	int ret;
 	char *p;
 
 	if (key == NULL) {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 08/10] eal: implement functions for thread barrier management
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (6 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                           ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 4d7d9242a9..0a9813794a 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -273,6 +273,67 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return pthread_mutex_destroy(mutex);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return ret;
+}
+
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to destroy barrier, ret = %d\n", ret);
+	}
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int rte_thread_cancel(rte_thread_t thread_id)
 {
 	/*
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index db8ef20930..b06443cf23 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -29,6 +29,11 @@ extern "C" {
 #include <rte_thread_types.h>
 #endif
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
 /**
  * Thread id descriptor.
  */
@@ -56,6 +61,13 @@ typedef struct {
 	rte_cpuset_t cpuset; /**< thread affinity */
 } rte_thread_attr_t;
 
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void* barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -300,6 +312,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex_t *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex_t *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier_t *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier_t *barrier);
+
 /**
  * Terminates a thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 239aa6be5d..2e657bbde8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -552,6 +552,62 @@ rte_thread_mutex_destroy(rte_thread_mutex_t *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier_t *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier_t *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier_t *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_cancel(rte_thread_t thread_id)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 09/10] eal: add EAL argument for setting thread priority
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (7 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ff5861b5f3..9d29696b84 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2088,6 +2113,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (8 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-06-04 23:44                         ` Narcisa Ana Maria Vasile
  2021-06-08  5:50                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-04 23:44 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Rename pthread_* occurrences with the new rte_thread_* API.
Enable the new API in the build system.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/process.h                            |   8 +-
 app/test/test_lcores.c                        |  16 +-
 app/test/test_link_bonding.c                  |  10 +-
 app/test/test_lpm_perf.c                      |  12 +-
 config/meson.build                            |   4 +
 drivers/bus/dpaa/base/qbman/bman_driver.c     |   5 +-
 drivers/bus/dpaa/base/qbman/dpaa_sys.c        |  14 +-
 drivers/bus/dpaa/base/qbman/process.c         |   6 +-
 drivers/bus/dpaa/dpaa_bus.c                   |  14 +-
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  19 +-
 drivers/compress/mlx5/mlx5_compress.c         |  10 +-
 drivers/event/dlb2/pf/base/dlb2_osdep.h       |   4 +-
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  18 +-
 drivers/net/ark/ark_ethdev.c                  |   2 +-
 drivers/net/ark/ark_pktgen.c                  |   4 +-
 drivers/net/atlantic/atl_ethdev.c             |   4 +-
 drivers/net/atlantic/atl_types.h              |   5 +-
 .../net/atlantic/hw_atl/hw_atl_utils_fw2x.c   |  26 +--
 drivers/net/axgbe/axgbe_common.h              |   2 +-
 drivers/net/axgbe/axgbe_dev.c                 |   8 +-
 drivers/net/axgbe/axgbe_ethdev.c              |   8 +-
 drivers/net/axgbe/axgbe_ethdev.h              |   8 +-
 drivers/net/axgbe/axgbe_i2c.c                 |   4 +-
 drivers/net/axgbe/axgbe_mdio.c                |   8 +-
 drivers/net/axgbe/axgbe_phy_impl.c            |   6 +-
 drivers/net/bnxt/bnxt.h                       |  16 +-
 drivers/net/bnxt/bnxt_cpr.c                   |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                |  52 ++---
 drivers/net/bnxt/bnxt_irq.c                   |   8 +-
 drivers/net/bnxt/bnxt_reps.c                  |  10 +-
 drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  34 ++--
 drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   4 +-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  24 +--
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h          |   2 +-
 drivers/net/ena/base/ena_plat_dpdk.h          |  12 +-
 drivers/net/enic/enic.h                       |   2 +-
 drivers/net/ice/ice_dcf_parent.c              |   6 +-
 drivers/net/ipn3ke/ipn3ke_representor.c       |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c              |   2 +-
 drivers/net/ixgbe/ixgbe_ethdev.h              |   2 +-
 drivers/net/kni/rte_eth_kni.c                 |   8 +-
 drivers/net/mlx5/linux/mlx5_os.c              |   2 +-
 drivers/net/mlx5/mlx5.c                       |  20 +-
 drivers/net/mlx5/mlx5.h                       |   2 +-
 drivers/net/mlx5/mlx5_txpp.c                  |   8 +-
 drivers/net/mlx5/windows/mlx5_flow_os.c       |  10 +-
 drivers/net/mlx5/windows/mlx5_os.c            |   2 +-
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/vhost/rte_eth_vhost.c             |  24 +--
 .../net/virtio/virtio_user/virtio_user_dev.c  |  30 +--
 .../net/virtio/virtio_user/virtio_user_dev.h  |   2 +-
 drivers/raw/ifpga/ifpga_rawdev.c              |   6 +-
 drivers/vdpa/ifc/ifcvf_vdpa.c                 |  46 ++---
 drivers/vdpa/mlx5/mlx5_vdpa.c                 |  24 +--
 drivers/vdpa/mlx5/mlx5_vdpa.h                 |   4 +-
 drivers/vdpa/mlx5/mlx5_vdpa_event.c           |  46 ++---
 examples/kni/main.c                           |   6 +-
 .../performance-thread/pthread_shim/main.c    |   2 +-
 examples/vhost/main.c                         |   2 +-
 examples/vhost_blk/vhost_blk.c                |  12 +-
 lib/eal/common/eal_common_options.c           |   6 +-
 lib/eal/common/eal_common_proc.c              |  48 ++---
 lib/eal/common/eal_common_thread.c            |  42 ++--
 lib/eal/common/eal_common_trace.c             |   2 +-
 lib/eal/common/eal_private.h                  |   2 +-
 lib/eal/common/eal_thread.h                   |   6 +
 lib/eal/common/malloc_mp.c                    |  32 +--
 lib/eal/common/meson.build                    |   1 +
 lib/eal/freebsd/eal.c                         |  42 +++-
 lib/eal/freebsd/eal_alarm.c                   |  12 +-
 lib/eal/freebsd/eal_interrupts.c              |   4 +-
 lib/eal/freebsd/eal_thread.c                  |  14 +-
 lib/eal/include/meson.build                   |   1 +
 lib/eal/include/rte_lcore.h                   |   8 +-
 lib/eal/include/rte_per_lcore.h               |   2 -
 lib/eal/linux/eal.c                           |  46 +++--
 lib/eal/linux/eal_alarm.c                     |  10 +-
 lib/eal/linux/eal_interrupts.c                |   4 +-
 lib/eal/linux/eal_thread.c                    |  18 +-
 lib/eal/linux/eal_timer.c                     |   2 +-
 lib/eal/unix/meson.build                      |   1 -
 lib/eal/unix/rte_thread.c                     |  92 ---------
 lib/eal/version.map                           |  22 ++
 lib/eal/windows/eal.c                         |  43 +++-
 lib/eal/windows/eal_interrupts.c              |  10 +-
 lib/eal/windows/eal_thread.c                  |  28 +--
 lib/eal/windows/eal_windows.h                 |  10 -
 lib/eal/windows/include/meson.build           |   1 +
 lib/eal/windows/include/pthread.h             | 192 ------------------
 lib/eal/windows/include/sched.h               |   2 +-
 lib/eal/windows/meson.build                   |   7 +-
 lib/ethdev/rte_ethdev.c                       |   4 +-
 lib/ethdev/rte_ethdev_core.h                  |   5 +-
 lib/ethdev/rte_flow.c                         |   4 +-
 lib/eventdev/rte_event_eth_rx_adapter.c       |   6 +-
 lib/vhost/fd_man.c                            |  40 ++--
 lib/vhost/fd_man.h                            |   6 +-
 lib/vhost/socket.c                            | 130 ++++++------
 lib/vhost/vhost.c                             |  10 +-
 meson_options.txt                             |   2 +
 100 files changed, 703 insertions(+), 887 deletions(-)
 delete mode 100644 lib/eal/unix/rte_thread.c
 delete mode 100644 lib/eal/windows/include/pthread.h

diff --git a/app/test/process.h b/app/test/process.h
index a09a088477..9e4be17bad 100644
--- a/app/test/process.h
+++ b/app/test/process.h
@@ -26,7 +26,7 @@
 
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-#include <pthread.h>
+#include <rte_thread.h>
 extern void *send_pkts(void *empty);
 extern uint16_t flag_for_send_pkts;
 #endif
@@ -47,7 +47,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	char path[32];
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
-	pthread_t thread;
+	rte_thread_t thread;
 	int rc;
 #endif
 #endif
@@ -128,7 +128,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_LIB_PDUMP
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
-		rc = pthread_create(&thread, NULL, &send_pkts, NULL);
+		rc = rte_thread_create(&thread, NULL, &send_pkts, NULL);
 		if (rc != 0) {
 			rte_panic("Cannot start send pkts thread: %s\n",
 				  strerror(rc));
@@ -143,7 +143,7 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 #ifdef RTE_NET_RING
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
-		pthread_join(thread, NULL);
+		rte_thread_join(thread, NULL);
 	}
 #endif
 #endif
diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c
index 19a7ab9fce..c507e423e0 100644
--- a/app/test/test_lcores.c
+++ b/app/test/test_lcores.c
@@ -14,7 +14,7 @@
 struct thread_context {
 	enum { INIT, ERROR, DONE } state;
 	bool lcore_id_any;
-	pthread_t id;
+	rte_thread_t id;
 	unsigned int *registered_count;
 };
 
@@ -77,7 +77,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 		t->state = INIT;
 		t->registered_count = &registered_count;
 		t->lcore_id_any = false;
-		if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+		if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 			break;
 		non_eal_threads_count++;
 	}
@@ -96,7 +96,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) == 0) {
+	if (rte_thread_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(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -110,7 +110,7 @@ test_non_eal_lcores(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -262,7 +262,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = false;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -285,7 +285,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	t->state = INIT;
 	t->registered_count = &registered_count;
 	t->lcore_id_any = true;
-	if (pthread_create(&t->id, NULL, thread_loop, t) != 0)
+	if (rte_thread_create(&t->id, NULL, thread_loop, t) != 0)
 		goto cleanup_threads;
 	non_eal_threads_count++;
 	while (__atomic_load_n(&registered_count, __ATOMIC_ACQUIRE) !=
@@ -309,7 +309,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	ret = 0;
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 		if (t->state != DONE)
 			ret = -1;
 	}
@@ -330,7 +330,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count)
 	__atomic_store_n(&registered_count, 0, __ATOMIC_RELEASE);
 	for (i = 0; i < non_eal_threads_count; i++) {
 		t = &thread_contexts[i];
-		pthread_join(t->id, NULL);
+		rte_thread_join(t->id, NULL);
 	}
 error:
 	if (handle[1] != NULL)
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 8a5c8310a8..3d9663f5ee 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -203,7 +203,7 @@ configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
 static int slaves_initialized;
 static int mac_slaves_initialized;
 
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mutex = RTE_THREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
 
 
@@ -1191,11 +1191,11 @@ test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
 		void *param __rte_unused,
 		void *ret_param __rte_unused)
 {
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	test_lsc_interrupt_count++;
 
 	pthread_cond_signal(&cvar);
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	return 0;
 }
@@ -1220,11 +1220,11 @@ lsc_timeout(int wait_us)
 		ts.tv_sec += 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	rte_thread_mutex_lock(&mutex);
 	if (test_lsc_interrupt_count < 1)
 		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
 
-	pthread_mutex_unlock(&mutex);
+	rte_thread_mutex_unlock(&mutex);
 
 	if (retval == 0 && test_lsc_interrupt_count < 1)
 		return -1;
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 2bed00d064..ce79d9c17a 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -25,7 +25,7 @@ static volatile uint32_t thr_id;
 static uint64_t gwrite_cycles;
 static uint32_t num_writers;
 /* LPM APIs are not thread safe, use mutex to provide thread safety */
-static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t lpm_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Report quiescent state interval every 1024 lookups. Larger critical
  * sections in reader will result in writer polling multiple times.
@@ -443,7 +443,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 		/* Add all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip,
 					large_ldepth_route_table[j].depth,
 					next_hop_add) != 0) {
@@ -452,13 +452,13 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 
 		/* Delete all the entries */
 		for (j = si; j < ei; j++) {
 			if (num_writers > 1)
-				pthread_mutex_lock(&lpm_mutex);
+				rte_thread_mutex_lock(&lpm_mutex);
 			if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip,
 				large_ldepth_route_table[j].depth) != 0) {
 				printf("Failed to delete iteration %d, route# %d\n",
@@ -466,7 +466,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 				goto error;
 			}
 			if (num_writers > 1)
-				pthread_mutex_unlock(&lpm_mutex);
+				rte_thread_mutex_unlock(&lpm_mutex);
 		}
 	}
 
@@ -478,7 +478,7 @@ test_lpm_rcu_qsbr_writer(void *arg)
 
 error:
 	if (num_writers > 1)
-		pthread_mutex_unlock(&lpm_mutex);
+		rte_thread_mutex_unlock(&lpm_mutex);
 	return -1;
 }
 
diff --git a/config/meson.build b/config/meson.build
index 017bb2efbb..4070eb200d 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -262,6 +262,10 @@ else # for 32-bit we need smaller reserved memory areas
     dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
 endif
 
+if is_windows
+	dpdk_conf.set('RTE_USE_WINDOWS_THREAD_TYPES', not get_option('use_external_thread_lib'))
+endif
+
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index ee35e03da1..c66a0946ca 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -38,11 +38,10 @@ static int fsl_bman_portal_init(uint32_t idx, int is_shared)
 	struct dpaa_ioctl_irq_map irq_map;
 
 	/* Verify the thread's cpu-affinity */
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-				     &cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
 	if (ret) {
 		errno = ret;
-		err(0, "pthread_getaffinity_np()");
+		err(0, "rte_thread_get_affinity_by_id()");
 		return ret;
 	}
 	pcfg.cpu = -1;
diff --git a/drivers/bus/dpaa/base/qbman/dpaa_sys.c b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
index 9d6bfd40a2..dc5f02bec1 100644
--- a/drivers/bus/dpaa/base/qbman/dpaa_sys.c
+++ b/drivers/bus/dpaa/base/qbman/dpaa_sys.c
@@ -18,16 +18,16 @@ struct process_interrupt {
 };
 
 static COMPAT_LIST_HEAD(process_irq_list);
-static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t process_irq_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void process_interrupt_install(struct process_interrupt *irq)
 {
 	int ret;
 	/* Add the irq to the end of the list */
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_add_tail(&irq->node, &process_irq_list);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -35,10 +35,10 @@ static void process_interrupt_remove(struct process_interrupt *irq)
 {
 	int ret;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_del(&irq->node);
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 }
 
@@ -47,14 +47,14 @@ static struct process_interrupt *process_interrupt_find(int irq_num)
 	int ret;
 	struct process_interrupt *i = NULL;
 
-	ret = pthread_mutex_lock(&process_irq_lock);
+	ret = rte_thread_mutex_lock(&process_irq_lock);
 	assert(!ret);
 	list_for_each_entry(i, &process_irq_list, node) {
 		if (i->irq == irq_num)
 			goto done;
 	}
 done:
-	ret = pthread_mutex_unlock(&process_irq_lock);
+	ret = rte_thread_mutex_unlock(&process_irq_lock);
 	assert(!ret);
 	return i;
 }
diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c
index 9bc92681cd..6d2d10cdf0 100644
--- a/drivers/bus/dpaa/base/qbman/process.c
+++ b/drivers/bus/dpaa/base/qbman/process.c
@@ -21,7 +21,7 @@
  * what the lock is for.
  */
 static int fd = -1;
-static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t fd_init_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static int check_fd(void)
 {
@@ -29,12 +29,12 @@ static int check_fd(void)
 
 	if (fd >= 0)
 		return 0;
-	ret = pthread_mutex_lock(&fd_init_lock);
+	ret = rte_thread_mutex_lock(&fd_init_lock);
 	assert(!ret);
 	/* check again with the lock held */
 	if (fd < 0)
 		fd = open(PROCESS_PATH, O_RDWR);
-	ret = pthread_mutex_unlock(&fd_init_lock);
+	ret = rte_thread_mutex_unlock(&fd_init_lock);
 	assert(!ret);
 	return (fd >= 0) ? 0 : -ENODEV;
 }
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 2f48d4036b..bd83cab577 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -10,7 +10,7 @@
 #include <limits.h>
 #include <sched.h>
 #include <signal.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
 #include <sys/eventfd.h>
@@ -48,7 +48,7 @@ static struct rte_dpaa_bus rte_dpaa_bus;
 struct netcfg_info *dpaa_netcfg;
 
 /* define a variable to hold the portal_key, once created.*/
-static pthread_key_t dpaa_portal_key;
+static rte_thread_key dpaa_portal_key;
 
 unsigned int dpaa_svr_family;
 
@@ -316,10 +316,10 @@ int rte_dpaa_portal_init(void *arg)
 	DPAA_PER_LCORE_PORTAL->bman_idx = bman_get_portal_index();
 	DPAA_PER_LCORE_PORTAL->tid = syscall(SYS_gettid);
 
-	ret = pthread_setspecific(dpaa_portal_key,
+	ret = rte_thread_value_set(dpaa_portal_key,
 				  (void *)DPAA_PER_LCORE_PORTAL);
 	if (ret) {
-		DPAA_BUS_LOG(ERR, "pthread_setspecific failed on core %u"
+		DPAA_BUS_LOG(ERR, "rte_thread_value_set failed on core %u"
 			     " (lcore=%u) with ret: %d", cpu, lcore, ret);
 		dpaa_portal_finish(NULL);
 
@@ -377,7 +377,7 @@ dpaa_portal_finish(void *arg)
 	bman_thread_finish();
 	qman_thread_finish();
 
-	pthread_setspecific(dpaa_portal_key, NULL);
+	rte_thread_value_set(dpaa_portal_key, NULL);
 
 	rte_free(dpaa_io_portal);
 	dpaa_io_portal = NULL;
@@ -453,9 +453,9 @@ rte_dpaa_bus_scan(void)
 	/* create the key, supplying a function that'll be invoked
 	 * when a portal affined thread will be deleted.
 	 */
-	ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
+	ret = rte_thread_key_create(&dpaa_portal_key, dpaa_portal_finish);
 	if (ret) {
-		DPAA_BUS_LOG(DEBUG, "Unable to create pthread key. (%d)", ret);
+		DPAA_BUS_LOG(DEBUG, "Unable to create thread key. (%d)", ret);
 		dpaa_clean_device_list();
 		return ret;
 	}
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index c6f8312a1d..dffbdff666 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -13,7 +13,7 @@
 #include <stdarg.h>
 #include <inttypes.h>
 #include <signal.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <sys/ioctl.h>
@@ -59,7 +59,7 @@ uint8_t dpaa2_dqrr_size;
 uint8_t dpaa2_eqcr_size;
 
 /* Variable to hold the portal_key, once created.*/
-static pthread_key_t dpaa2_portal_key;
+static rte_thread_key dpaa2_portal_key;
 
 /*Stashing Macros default for LS208x*/
 static int dpaa2_core_cluster_base = 0x04;
@@ -92,10 +92,9 @@ dpaa2_get_core_id(void)
 	rte_cpuset_t cpuset;
 	int i, ret, cpu_id = -1;
 
-	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
-		&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_getaffinity_np() failed");
+		DPAA2_BUS_ERR("rte_thread_get_affinity_by_id() failed");
 		return ret;
 	}
 
@@ -296,9 +295,9 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(void)
 		}
 	}
 
-	ret = pthread_setspecific(dpaa2_portal_key, (void *)dpio_dev);
+	ret = rte_thread_value_set(dpaa2_portal_key, (void *)dpio_dev);
 	if (ret) {
-		DPAA2_BUS_ERR("pthread_setspecific failed with ret: %d", ret);
+		DPAA2_BUS_ERR("rte_thread_value_set failed with ret: %d", ret);
 		dpaa2_put_qbman_swp(dpio_dev);
 		return NULL;
 	}
@@ -357,7 +356,7 @@ static void dpaa2_portal_finish(void *arg)
 	dpaa2_put_qbman_swp(RTE_PER_LCORE(_dpaa2_io).dpio_dev);
 	dpaa2_put_qbman_swp(RTE_PER_LCORE(_dpaa2_io).ethrx_dpio_dev);
 
-	pthread_setspecific(dpaa2_portal_key, NULL);
+	rte_thread_value_set(dpaa2_portal_key, NULL);
 }
 
 static int
@@ -515,10 +514,10 @@ dpaa2_create_dpio_device(int vdev_fd,
 		/* create the key, supplying a function that'll be invoked
 		 * when a portal affined thread will be deleted.
 		 */
-		ret = pthread_key_create(&dpaa2_portal_key,
+		ret = rte_thread_key_create(&dpaa2_portal_key,
 					 dpaa2_portal_finish);
 		if (ret) {
-			DPAA2_BUS_DEBUG("Unable to create pthread key (%d)",
+			DPAA2_BUS_DEBUG("Unable to create thread key (%d)",
 					ret);
 			goto err;
 		}
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index 80c564f10b..b1f14ea606 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -72,7 +72,7 @@ struct mlx5_compress_qp {
 
 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
 				TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 int mlx5_compress_logtype;
 
@@ -804,9 +804,9 @@ mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
 	}
 	priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
 	priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 }
 
@@ -826,13 +826,13 @@ mlx5_compress_pci_remove(struct rte_pci_device *pdev)
 {
 	struct mlx5_compress_priv *priv = NULL;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
 		if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
 			break;
 	if (priv)
 		TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (priv) {
 		mlx5_mr_release_cache(&priv->mr_scache);
 		mlx5_compress_hw_global_release(priv);
diff --git a/drivers/event/dlb2/pf/base/dlb2_osdep.h b/drivers/event/dlb2/pf/base/dlb2_osdep.h
index cffe22f3c5..bdd174821c 100644
--- a/drivers/event/dlb2/pf/base/dlb2_osdep.h
+++ b/drivers/event/dlb2/pf/base/dlb2_osdep.h
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
@@ -194,7 +194,7 @@ static void *dlb2_complete_queue_map_unmap(void *__args)
 static inline void os_schedule_work(struct dlb2_hw *hw)
 {
 	struct dlb2_dev *dlb2_dev;
-	pthread_t complete_queue_map_unmap_thread;
+	rte_thread_t complete_queue_map_unmap_thread;
 	int ret;
 
 	dlb2_dev = container_of(hw, struct dlb2_dev, hw);
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index eb5660a3dc..41fe063639 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -178,7 +178,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 static inline int
@@ -676,7 +676,7 @@ find_internal_resource(struct pmd_internals *port_int)
 	if (port_int == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		struct pmd_internals *list_int =
@@ -687,7 +687,7 @@ find_internal_resource(struct pmd_internals *port_int)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -725,7 +725,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	if (mb_pool == NULL)
 		return ret;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internals = list->eth_dev->data->dev_private;
@@ -751,7 +751,7 @@ get_shared_umem(struct pkt_rx_queue *rxq, const char *ifname,
 	}
 
 out:
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return ret;
 }
@@ -780,9 +780,9 @@ eth_dev_configure(struct rte_eth_dev *dev)
 			return -1;
 
 		list->eth_dev = dev;
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_INSERT_TAIL(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 	}
 
 	return 0;
@@ -948,9 +948,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 		/* Remove ethdev from list used to track and share UMEMs */
 		list = find_internal_resource(internals);
 		if (list) {
-			pthread_mutex_lock(&internal_list_lock);
+			rte_thread_mutex_lock(&internal_list_lock);
 			TAILQ_REMOVE(&internal_list, list, next);
-			pthread_mutex_unlock(&internal_list_lock);
+			rte_thread_mutex_unlock(&internal_list_lock);
 			rte_free(list);
 		}
 	}
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 377299b14c..481442b31e 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -563,7 +563,7 @@ eth_ark_dev_start(struct rte_eth_dev *dev)
 		ark_pktchkr_run(ark->pc);
 
 	if (ark->start_pg && (dev->data->port_id == 0)) {
-		pthread_t thread;
+		rte_thread_t thread;
 
 		/* Delay packet generatpr start allow the hardware to be ready
 		 * This is only used for sanity checking with internal generator
diff --git a/drivers/net/ark/ark_pktgen.c b/drivers/net/ark/ark_pktgen.c
index 515bfe461c..58ff65b5d5 100644
--- a/drivers/net/ark/ark_pktgen.c
+++ b/drivers/net/ark/ark_pktgen.c
@@ -3,7 +3,7 @@
  */
 
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
@@ -475,7 +475,7 @@ ark_pktgen_delay_start(void *arg)
 	 * perform a blind sleep here to ensure that the external test
 	 * application has time to setup the test before we generate packets
 	 */
-	pthread_detach(pthread_self());
+	rte_thread_detach(rte_thread_self());
 	usleep(100000);
 	ark_pktgen_run(inst);
 	return NULL;
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 0ce35eb519..2b86f01a25 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -405,7 +405,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	hw->aq_nic_cfg = &adapter->hw_cfg;
 
-	pthread_mutex_init(&hw->mbox_mutex, NULL);
+	rte_thread_mutex_init(&hw->mbox_mutex);
 
 	/* disable interrupt */
 	atl_disable_intr(hw);
@@ -712,7 +712,7 @@ atl_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     atl_dev_interrupt_handler, dev);
 
-	pthread_mutex_destroy(&hw->mbox_mutex);
+	rte_thread_mutex_destroy(&hw->mbox_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h
index e813d9f326..93e41aa26a 100644
--- a/drivers/net/atlantic/atl_types.h
+++ b/drivers/net/atlantic/atl_types.h
@@ -10,7 +10,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <netinet/in.h>
-#include <pthread.h>
+#include <rte_compat.h>
+#include <rte_thread.h>
 
 #include <rte_common.h>
 
@@ -141,7 +142,7 @@ struct aq_hw_s {
 	u32 rpc_tid;
 	struct hw_aq_atl_utils_fw_rpc rpc;
 
-	pthread_mutex_t mbox_mutex;
+	rte_thread_mutex_t mbox_mutex;
 };
 
 struct aq_fw_ops {
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 3a7faf405c..15b80584f8 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -6,7 +6,7 @@
  */
 
 #include <rte_ether.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include "../atl_hw_regs.h"
 
 #include "../atl_types.h"
@@ -218,7 +218,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	u32 mac_addr[2] = { 0 };
 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	if (efuse_addr != 0) {
 		err = hw_atl_utils_fw_downld_dwords(self,
@@ -257,7 +257,7 @@ int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -269,7 +269,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
 
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to update */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
@@ -286,7 +286,7 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	err = hw_atl_utils_update_stats(self);
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 
@@ -299,7 +299,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
 	u32 temp_res;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
@@ -317,7 +317,7 @@ static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
 				sizeof(temp_res) / sizeof(u32));
 
 
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	if (err)
 		return err;
@@ -536,7 +536,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	request.msg_id = 0;
 	request.device_id = dev_addr;
@@ -605,7 +605,7 @@ static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -626,7 +626,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	request.address = offset;
 	request.length = len;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write SMBUS request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -694,7 +694,7 @@ static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
 	}
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
@@ -712,7 +712,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
 		return -EOPNOTSUPP;
 
-	pthread_mutex_lock(&self->mbox_mutex);
+	rte_thread_mutex_lock(&self->mbox_mutex);
 
 	/* Write macsec request to cfg memory */
 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
@@ -742,7 +742,7 @@ static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
 
 exit:
-	pthread_mutex_unlock(&self->mbox_mutex);
+	rte_thread_mutex_unlock(&self->mbox_mutex);
 
 	return err;
 }
diff --git a/drivers/net/axgbe/axgbe_common.h b/drivers/net/axgbe/axgbe_common.h
index df0aa21a9b..a7b892b806 100644
--- a/drivers/net/axgbe/axgbe_common.h
+++ b/drivers/net/axgbe/axgbe_common.h
@@ -19,7 +19,7 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 786288a7b0..197c722901 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -167,12 +167,12 @@ static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	mmd_data = XPCS16_IOREAD(pdata, offset);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 
 	return mmd_data;
 }
@@ -201,12 +201,12 @@ static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
 	index = mmd_address & ~pdata->xpcs_window_mask;
 	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
-	pthread_mutex_lock(&pdata->xpcs_mutex);
+	rte_thread_mutex_lock(&pdata->xpcs_mutex);
 
 	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
 	XPCS16_IOWRITE(pdata, offset, mmd_data);
 
-	pthread_mutex_unlock(&pdata->xpcs_mutex);
+	rte_thread_mutex_unlock(&pdata->xpcs_mutex);
 }
 
 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 9cb4818af1..caf5a4476f 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2311,10 +2311,10 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 	pdata->tx_desc_count = AXGBE_MAX_RING_DESC;
 	pdata->rx_desc_count = AXGBE_MAX_RING_DESC;
-	pthread_mutex_init(&pdata->xpcs_mutex, NULL);
-	pthread_mutex_init(&pdata->i2c_mutex, NULL);
-	pthread_mutex_init(&pdata->an_mutex, NULL);
-	pthread_mutex_init(&pdata->phy_mutex, NULL);
+	rte_thread_mutex_init(&pdata->xpcs_mutex);
+	rte_thread_mutex_init(&pdata->i2c_mutex);
+	rte_thread_mutex_init(&pdata->an_mutex);
+	rte_thread_mutex_init(&pdata->phy_mutex);
 
 	ret = pdata->phy_if.phy_init(pdata);
 	if (ret) {
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index a6226729fe..cfd436fa63 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -602,10 +602,10 @@ struct axgbe_port {
 	int phy_link;
 	int phy_speed;
 
-	pthread_mutex_t xpcs_mutex;
-	pthread_mutex_t i2c_mutex;
-	pthread_mutex_t an_mutex;
-	pthread_mutex_t phy_mutex;
+	rte_thread_mutex_t xpcs_mutex;
+	rte_thread_mutex_t i2c_mutex;
+	rte_thread_mutex_t an_mutex;
+	rte_thread_mutex_t phy_mutex;
 
 	/* Flow control settings */
 	unsigned int pause_autoneg;
diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c
index ab3738a12e..c17f9a8b9e 100644
--- a/drivers/net/axgbe/axgbe_i2c.c
+++ b/drivers/net/axgbe/axgbe_i2c.c
@@ -229,7 +229,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	int ret;
 	uint64_t timeout;
 
-	pthread_mutex_lock(&pdata->i2c_mutex);
+	rte_thread_mutex_lock(&pdata->i2c_mutex);
 	ret = axgbe_i2c_disable(pdata);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "failed to disable i2c master\n");
@@ -282,7 +282,7 @@ static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
 	}
 
 unlock:
-	pthread_mutex_unlock(&pdata->i2c_mutex);
+	rte_thread_mutex_unlock(&pdata->i2c_mutex);
 	return ret;
 }
 
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 4f98e695ae..5f3d9b360e 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -686,9 +686,9 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
 	if (pdata->an_int) {
 		/* Clear the interrupt(s) that fired and process them */
 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
-		pthread_mutex_lock(&pdata->an_mutex);
+		rte_thread_mutex_lock(&pdata->an_mutex);
 		axgbe_an73_state_machine(pdata);
-		pthread_mutex_unlock(&pdata->an_mutex);
+		rte_thread_mutex_unlock(&pdata->an_mutex);
 	} else {
 		/* Enable AN interrupts */
 		axgbe_an73_enable_interrupts(pdata);
@@ -977,7 +977,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 {
 	int ret;
 
-	pthread_mutex_lock(&pdata->an_mutex);
+	rte_thread_mutex_lock(&pdata->an_mutex);
 
 	ret = __axgbe_phy_config_aneg(pdata);
 	if (ret)
@@ -985,7 +985,7 @@ static int axgbe_phy_config_aneg(struct axgbe_port *pdata)
 	else
 		rte_bit_relaxed_clear32(AXGBE_LINK_ERR, &pdata->dev_state);
 
-	pthread_mutex_unlock(&pdata->an_mutex);
+	rte_thread_mutex_unlock(&pdata->an_mutex);
 
 	return ret;
 }
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 02236ec192..1e1d6358d8 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -403,7 +403,7 @@ static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
 
 	phy_data->comm_owned = 0;
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 }
 
 static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
@@ -416,7 +416,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 	 * the driver needs to take the software mutex and then the hardware
 	 * mutexes before being able to use the busses.
 	 */
-	pthread_mutex_lock(&pdata->phy_mutex);
+	rte_thread_mutex_lock(&pdata->phy_mutex);
 
 	if (phy_data->comm_owned)
 		return 0;
@@ -447,7 +447,7 @@ static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
 		return 0;
 	}
 
-	pthread_mutex_unlock(&pdata->phy_mutex);
+	rte_thread_mutex_unlock(&pdata->phy_mutex);
 
 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
 
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index db67bff127..64678ee145 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -534,8 +534,8 @@ struct bnxt_mark_info {
 
 struct bnxt_rep_info {
 	struct rte_eth_dev	*vfr_eth_dev;
-	pthread_mutex_t		vfr_lock;
-	pthread_mutex_t		vfr_start_lock;
+	rte_thread_mutex_t		vfr_lock;
+	rte_thread_mutex_t		vfr_start_lock;
 	bool			conduit_valid;
 };
 
@@ -687,7 +687,7 @@ struct bnxt {
 #define BNXT_FW_CAP_ADV_FLOW_COUNTERS	BIT(6)
 #define BNXT_FW_CAP_LINK_ADMIN		BIT(7)
 
-	pthread_mutex_t         flow_lock;
+	rte_thread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
@@ -741,18 +741,18 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	/* synchronize between dev_configure_op and int handler */
-	pthread_mutex_t			def_cp_lock;
+	rte_thread_mutex_t			def_cp_lock;
 	/* synchronize between dev_start_op and async evt handler
 	 * Locking sequence in async evt handler will be
 	 * def_cp_lock
 	 * health_check_lock
 	 */
-	pthread_mutex_t			health_check_lock;
+	rte_thread_mutex_t			health_check_lock;
 	/* synchronize between dev_stop/dev_close_op and
 	 * error recovery thread triggered as part of
 	 * HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY
 	 */
-	pthread_mutex_t			err_recovery_lock;
+	rte_thread_mutex_t			err_recovery_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
@@ -944,10 +944,10 @@ uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 extern const struct rte_flow_ops bnxt_flow_ops;
 
 #define bnxt_acquire_flow_lock(bp) \
-	pthread_mutex_lock(&(bp)->flow_lock)
+	rte_thread_mutex_lock(&(bp)->flow_lock)
 
 #define bnxt_release_flow_lock(bp) \
-	pthread_mutex_unlock(&(bp)->flow_lock)
+	rte_thread_mutex_unlock(&(bp)->flow_lock)
 
 #define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
 	if ((vnic_id) >= (bp)->max_vnics) { \
diff --git a/drivers/net/bnxt/bnxt_cpr.c b/drivers/net/bnxt/bnxt_cpr.c
index 2c7fd78c3d..a50511047c 100644
--- a/drivers/net/bnxt/bnxt_cpr.c
+++ b/drivers/net/bnxt/bnxt_cpr.c
@@ -135,7 +135,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 			return;
 		}
 
-		pthread_mutex_lock(&bp->err_recovery_lock);
+		rte_thread_mutex_lock(&bp->err_recovery_lock);
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -157,7 +157,7 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		}
 
 		bp->flags |= BNXT_FLAG_FW_RESET;
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		rte_eal_alarm_set(US_PER_MS, bnxt_dev_reset_and_resume,
 				  (void *)bp);
 		break;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 3778e28cca..d00c8011ba 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1049,7 +1049,7 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		 * are calculated correctly.
 		 */
 
-		pthread_mutex_lock(&bp->def_cp_lock);
+		rte_thread_mutex_lock(&bp->def_cp_lock);
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			bnxt_disable_int(bp);
@@ -1059,20 +1059,20 @@ static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
 		rc = bnxt_hwrm_func_reserve_vf_resc(bp, false);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "HWRM resource alloc fail:%x\n", rc);
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return -ENOSPC;
 		}
 
 		if (!BNXT_HAS_NQ(bp) && bp->async_cp_ring) {
 			rc = bnxt_alloc_async_cp_ring(bp);
 			if (rc) {
-				pthread_mutex_unlock(&bp->def_cp_lock);
+				rte_thread_mutex_unlock(&bp->def_cp_lock);
 				return rc;
 			}
 			bnxt_enable_int(bp);
 		}
 
-		pthread_mutex_unlock(&bp->def_cp_lock);
+		rte_thread_mutex_unlock(&bp->def_cp_lock);
 	}
 
 	/* Inherit new configurations */
@@ -1456,14 +1456,14 @@ static int bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error..Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return bnxt_dev_stop(eth_dev);
 }
@@ -1545,13 +1545,13 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 static void
 bnxt_uninit_locks(struct bnxt *bp)
 {
-	pthread_mutex_destroy(&bp->flow_lock);
-	pthread_mutex_destroy(&bp->def_cp_lock);
-	pthread_mutex_destroy(&bp->health_check_lock);
-	pthread_mutex_destroy(&bp->err_recovery_lock);
+	rte_thread_mutex_destroy(&bp->flow_lock);
+	rte_thread_mutex_destroy(&bp->def_cp_lock);
+	rte_thread_mutex_destroy(&bp->health_check_lock);
+	rte_thread_mutex_destroy(&bp->err_recovery_lock);
 	if (bp->rep_info) {
-		pthread_mutex_destroy(&bp->rep_info->vfr_lock);
-		pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_lock);
+		rte_thread_mutex_destroy(&bp->rep_info->vfr_start_lock);
 	}
 }
 
@@ -1583,14 +1583,14 @@ static int bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	pthread_mutex_lock(&bp->err_recovery_lock);
+	rte_thread_mutex_lock(&bp->err_recovery_lock);
 	if (bp->flags & BNXT_FLAG_FW_RESET) {
 		PMD_DRV_LOG(ERR,
 			    "Adapter recovering from error...Please retry\n");
-		pthread_mutex_unlock(&bp->err_recovery_lock);
+		rte_thread_mutex_unlock(&bp->err_recovery_lock);
 		return -EAGAIN;
 	}
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	/* cancel the recovery handler before remove dev */
 	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
@@ -4108,7 +4108,7 @@ static void bnxt_dev_recover(void *arg)
 		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 
 	return;
 err_start:
@@ -4116,7 +4116,7 @@ static void bnxt_dev_recover(void *arg)
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
-	pthread_mutex_unlock(&bp->err_recovery_lock);
+	rte_thread_mutex_unlock(&bp->err_recovery_lock);
 	PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
 }
 
@@ -4292,7 +4292,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
-	pthread_mutex_lock(&bp->health_check_lock);
+	rte_thread_mutex_lock(&bp->health_check_lock);
 
 	if (!bnxt_is_recovery_enabled(bp))
 		goto done;
@@ -4307,7 +4307,7 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
 
 done:
-	pthread_mutex_unlock(&bp->health_check_lock);
+	rte_thread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -5093,25 +5093,25 @@ bnxt_init_locks(struct bnxt *bp)
 {
 	int err;
 
-	err = pthread_mutex_init(&bp->flow_lock, NULL);
+	err = rte_thread_mutex_init(&bp->flow_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize flow_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
+	err = rte_thread_mutex_init(&bp->def_cp_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	err = rte_thread_mutex_init(&bp->health_check_lock);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 		return err;
 	}
 
-	err = pthread_mutex_init(&bp->err_recovery_lock, NULL);
+	err = rte_thread_mutex_init(&bp->err_recovery_lock);
 	if (err)
 		PMD_DRV_LOG(ERR, "Unable to initialize err_recovery_lock\n");
 
@@ -5894,14 +5894,14 @@ static int bnxt_init_rep_info(struct bnxt *bp)
 	for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
 		bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
 		bnxt_free_rep_info(bp);
 		return rc;
 	}
 
-	rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->rep_info->vfr_start_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
 		bnxt_free_rep_info(bp);
diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 8abbadb3d1..e1d980cf91 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -30,15 +30,15 @@ void bnxt_int_handler(void *param)
 		return;
 
 	raw_cons = cpr->cp_raw_cons;
-	pthread_mutex_lock(&bp->def_cp_lock);
+	rte_thread_mutex_lock(&bp->def_cp_lock);
 	while (1) {
 		if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
 		if (is_bnxt_in_error(bp)) {
-			pthread_mutex_unlock(&bp->def_cp_lock);
+			rte_thread_mutex_unlock(&bp->def_cp_lock);
 			return;
 		}
 
@@ -58,7 +58,7 @@ void bnxt_int_handler(void *param)
 	else
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 
-	pthread_mutex_unlock(&bp->def_cp_lock);
+	rte_thread_mutex_unlock(&bp->def_cp_lock);
 }
 
 int bnxt_free_int(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index bdbad53b7d..49d3ec66bc 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -120,7 +120,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 	qid = vfr_txq->txq->queue_id;
 	vf_rep_bp = vfr_txq->bp;
 	parent = vf_rep_bp->parent_dev->data->dev_private;
-	pthread_mutex_lock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_lock(&parent->rep_info->vfr_lock);
 	ptxq = parent->tx_queues[qid];
 
 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
@@ -132,7 +132,7 @@ bnxt_rep_tx_burst(void *tx_queue,
 
 	rc = bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
 	ptxq->vfr_tx_cfa_action = 0;
-	pthread_mutex_unlock(&parent->rep_info->vfr_lock);
+	rte_thread_mutex_unlock(&parent->rep_info->vfr_lock);
 
 	return rc;
 }
@@ -407,15 +407,15 @@ int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
 
 	BNXT_TF_DBG(DEBUG, "BNXT Port:%d VFR start\n", eth_dev->data->port_id);
-	pthread_mutex_lock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_lock(&rep_info->vfr_start_lock);
 	if (!rep_info->conduit_valid) {
 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
 		if (rc || !rep_info->conduit_valid) {
-			pthread_mutex_unlock(&rep_info->vfr_start_lock);
+			rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 			return rc;
 		}
 	}
-	pthread_mutex_unlock(&rep_info->vfr_start_lock);
+	rte_thread_mutex_unlock(&rep_info->vfr_start_lock);
 
 	rc = bnxt_vfr_alloc(eth_dev);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index 5c805eef97..455d83bef8 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -28,7 +28,7 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 			STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
 
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
-static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t bnxt_ulp_global_mutex = RTE_THREAD_MUTEX_INITIALIZER;
 
 /*
  * Allow the deletion of context only for the bnxt device that
@@ -640,7 +640,7 @@ ulp_ctx_detach(struct bnxt *bp)
 static void
 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 {
-	pthread_mutex_lock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_lock(&session->bnxt_ulp_mutex);
 
 	if (!session->bnxt_ulp_init) {
 		session->bnxt_ulp_init = true;
@@ -649,7 +649,7 @@ ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
 		*init = true;
 	}
 
-	pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+	rte_thread_mutex_unlock(&session->bnxt_ulp_mutex);
 }
 
 /*
@@ -690,7 +690,7 @@ ulp_session_init(struct bnxt *bp,
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
 
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 
 	session = ulp_get_session(pci_addr);
 	if (!session) {
@@ -701,17 +701,17 @@ ulp_session_init(struct bnxt *bp,
 		if (!session) {
 			BNXT_TF_DBG(ERR,
 				    "Allocation failed for bnxt_ulp_session\n");
-			pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+			rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 			return NULL;
 
 		} else {
 			/* Add it to the queue */
 			session->pci_info.domain = pci_addr->domain;
 			session->pci_info.bus = pci_addr->bus;
-			rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+			rc = rte_thread_mutex_init(&session->bnxt_ulp_mutex);
 			if (rc) {
 				BNXT_TF_DBG(ERR, "mutex create failed\n");
-				pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+				rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 				return NULL;
 			}
 			STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
@@ -719,7 +719,7 @@ ulp_session_init(struct bnxt *bp,
 		}
 	}
 	ulp_context_initialized(session, init);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	return session;
 }
 
@@ -734,12 +734,12 @@ ulp_session_deinit(struct bnxt_ulp_session_state *session)
 		return;
 
 	if (!session->cfg_data) {
-		pthread_mutex_lock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 		STAILQ_REMOVE(&bnxt_ulp_session_list, session,
 			      bnxt_ulp_session_state, next);
-		pthread_mutex_destroy(&session->bnxt_ulp_mutex);
+		rte_thread_mutex_destroy(&session->bnxt_ulp_mutex);
 		rte_free(session);
-		pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+		rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 	}
 }
 
@@ -892,7 +892,7 @@ bnxt_ulp_deinit(struct bnxt *bp,
 					 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
 
 	/* free the flow db lock */
-	pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
 
 	/* Delete the ulp context and tf session and free the ulp context */
 	ulp_ctx_deinit(bp, session);
@@ -917,7 +917,7 @@ bnxt_ulp_init(struct bnxt *bp,
 		goto jump_to_error;
 	}
 
-	rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
+	rc = rte_thread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
 		goto jump_to_error;
@@ -1117,9 +1117,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
 	/* Get the session details  */
 	pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
 	pci_addr = &pci_dev->addr;
-	pthread_mutex_lock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_lock(&bnxt_ulp_global_mutex);
 	session = ulp_get_session(pci_addr);
-	pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+	rte_thread_mutex_unlock(&bnxt_ulp_global_mutex);
 
 	/* session not found then just exit */
 	if (!session) {
@@ -1451,7 +1451,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return -1;
 
-	if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
+	if (rte_thread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
 		BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
 		return -1;
 	}
@@ -1465,5 +1465,5 @@ bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context	*ulp_ctx)
 	if (!ulp_ctx || !ulp_ctx->cfg_data)
 		return;
 
-	pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
+	rte_thread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
 }
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index 330965061a..88d64d703f 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -49,7 +49,7 @@ struct bnxt_ulp_data {
 	uint32_t			dev_id; /* Hardware device id */
 	uint32_t			ref_cnt;
 	struct bnxt_ulp_flow_db		*flow_db;
-	pthread_mutex_t			flow_db_lock;
+	rte_thread_mutex_t			flow_db_lock;
 	void				*mapper_data;
 	struct bnxt_ulp_port_db		*port_db;
 	struct bnxt_ulp_fc_info		*fc_info;
@@ -75,7 +75,7 @@ struct bnxt_ulp_pci_info {
 struct bnxt_ulp_session_state {
 	STAILQ_ENTRY(bnxt_ulp_session_state)	next;
 	bool					bnxt_ulp_init;
-	pthread_mutex_t				bnxt_ulp_mutex;
+	rte_thread_mutex_t				bnxt_ulp_mutex;
 	struct bnxt_ulp_pci_info		pci_info;
 	struct bnxt_ulp_data			*cfg_data;
 	struct tf				*g_tfp;
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index 3eddbd6831..26c3e7551c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -84,7 +84,7 @@ ulp_fc_mgr_init(struct bnxt_ulp_context *ctxt)
 	if (!ulp_fc_info)
 		goto error;
 
-	rc = pthread_mutex_init(&ulp_fc_info->fc_lock, NULL);
+	rc = rte_thread_mutex_init(&ulp_fc_info->fc_lock);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to initialize fc mutex\n");
 		goto error;
@@ -141,7 +141,7 @@ ulp_fc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_fc_mgr_thread_cancel(ctxt);
 
-	pthread_mutex_destroy(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_destroy(&ulp_fc_info->fc_lock);
 
 	for (i = 0; i < TF_DIR_MAX; i++)
 		rte_free(ulp_fc_info->sw_acc_tbl[i]);
@@ -383,7 +383,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		goto out;
 
 	if (!ulp_fc_info->num_entries) {
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
@@ -414,7 +414,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
 		}
 	}
 
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	/*
 	 * If cmd fails once, no need of
@@ -503,12 +503,12 @@ int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -535,14 +535,14 @@ int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return 0;
 }
@@ -607,7 +607,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 	hw_cntr_id = params.resource_hndl;
 	if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
-		pthread_mutex_lock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 		sw_cntr_idx = hw_cntr_id -
 			ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 		sw_acc_tbl_entry = &ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
@@ -621,7 +621,7 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
 			sw_acc_tbl_entry->pkt_count = 0;
 			sw_acc_tbl_entry->byte_count = 0;
 		}
-		pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+		rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 	} else if (params.resource_sub_type ==
 			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC) {
 		/* Get stats from the parent child table */
@@ -663,7 +663,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 	if (!ulp_fc_info)
 		return -EIO;
 
-	pthread_mutex_lock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	if (ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid) {
 		ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].parent_flow_id = fid;
@@ -672,7 +672,7 @@ int32_t ulp_fc_mgr_cntr_parent_flow_set(struct bnxt_ulp_context *ctxt,
 			    hw_cntr_id, fid);
 		rc = -ENOENT;
 	}
-	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
+	rte_thread_mutex_unlock(&ulp_fc_info->fc_lock);
 
 	return rc;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index 04cb86bea2..cb6bbcad6c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -47,7 +47,7 @@ struct bnxt_ulp_fc_info {
 	struct hw_fc_mem_info	shadow_hw_tbl[TF_DIR_MAX];
 	uint32_t		flags;
 	uint32_t		num_entries;
-	pthread_mutex_t		fc_lock;
+	rte_thread_mutex_t		fc_lock;
 };
 
 int32_t
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index f66df95591..923cef1b12 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -148,14 +148,14 @@ extern int ena_logtype_com;
 
 typedef struct {
 	pthread_cond_t cond;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 	uint8_t flag;
 } ena_wait_event_t;
 
 #define ENA_WAIT_EVENT_INIT(waitevent)					       \
 	do {								       \
 		ena_wait_event_t *_we = &(waitevent);			       \
-		pthread_mutex_init(&_we->mutex, NULL);			       \
+		rte_thread_mutex_init(&_we->mutex);				       \
 		pthread_cond_init(&_we->cond, NULL);			       \
 		_we->flag = 0;						       \
 	} while (0)
@@ -172,7 +172,7 @@ typedef struct {
 		wait.tv_sec = now.tv_sec + _tmo / 1000000UL;		       \
 		timeout_us = _tmo % 1000000UL;				       \
 		wait.tv_nsec = (now.tv_usec + timeout_us) * 1000UL;	       \
-		pthread_mutex_lock(&_we->mutex);			       \
+		rte_thread_mutex_lock(&_we->mutex);			       \
 		while (ret == 0 && !_we->flag) {			       \
 			ret = pthread_cond_timedwait(&_we->cond,	       \
 				&_we->mutex, &wait);			       \
@@ -185,15 +185,15 @@ typedef struct {
 			ena_trc_err(NULL,				       \
 				"Timeout waiting for " #waitevent "\n");       \
 		_we->flag = 0;						       \
-		pthread_mutex_unlock(&_we->mutex);			       \
+		rte_thread_mutex_unlock(&_we->mutex);			       \
 	} while (0)
 #define ENA_WAIT_EVENT_SIGNAL(waitevent)				       \
 	do {								       \
 		ena_wait_event_t *_we = &(waitevent);			       \
-		pthread_mutex_lock(&_we->mutex);			       \
+		rte_thread_mutex_lock(&_we->mutex);			       \
 		_we->flag = 1;						       \
 		pthread_cond_signal(&_we->cond);			       \
-		pthread_mutex_unlock(&_we->mutex);			       \
+		rte_thread_mutex_unlock(&_we->mutex);			       \
 	} while (0)
 /* pthread condition doesn't need to be rearmed after usage */
 #define ENA_WAIT_EVENT_CLEAR(...)
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 47bfdac2cf..db07c589b9 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -107,7 +107,7 @@ struct enic {
 	int iommu_groupid;
 	int eventfd;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	pthread_t err_intr_thread;
+	rte_thread_t err_intr_thread;
 	int promisc;
 	int allmulti;
 	uint8_t ig_vlan_strip_en;
diff --git a/drivers/net/ice/ice_dcf_parent.c b/drivers/net/ice/ice_dcf_parent.c
index 1d7aa8bc87..99eb940b87 100644
--- a/drivers/net/ice/ice_dcf_parent.c
+++ b/drivers/net/ice/ice_dcf_parent.c
@@ -3,7 +3,7 @@
  */
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <unistd.h>
 
 #include <rte_spinlock.h>
@@ -121,7 +121,7 @@ ice_dcf_vsi_update_service_handler(void *param)
 	struct ice_dcf_hw *hw = reset_param->dcf_hw;
 	struct ice_dcf_adapter *adapter;
 
-	pthread_detach(pthread_self());
+	rte_thread_detach(rte_thread_self());
 
 	rte_delay_us(ICE_DCF_VSI_UPDATE_SERVICE_INTERVAL);
 
@@ -156,7 +156,7 @@ start_vsi_reset_thread(struct ice_dcf_hw *dcf_hw, bool vfr, uint16_t vf_id)
 #define THREAD_NAME_LEN	16
 	struct ice_dcf_reset_event_param *param;
 	char name[THREAD_NAME_LEN];
-	pthread_t thread;
+	rte_thread_t thread;
 	int ret;
 
 	param = malloc(sizeof(*param));
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 589d9fa587..97e36a2e0e 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -27,7 +27,7 @@
 #include "ipn3ke_ethdev.h"
 
 static int ipn3ke_rpst_scan_num;
-static pthread_t ipn3ke_rpst_scan_thread;
+static rte_thread_t ipn3ke_rpst_scan_thread;
 
 /** Double linked list of representor port. */
 TAILQ_HEAD(ipn3ke_rpst_list, ipn3ke_rpst);
@@ -2614,11 +2614,11 @@ ipn3ke_rpst_scan_check(void)
 			return -1;
 		}
 	} else if (ipn3ke_rpst_scan_num == 0) {
-		ret = pthread_cancel(ipn3ke_rpst_scan_thread);
+		ret = rte_thread_cancel(ipn3ke_rpst_scan_thread);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ipn3ke_rpst_scan_thread, NULL);
+		ret = rte_thread_join(ipn3ke_rpst_scan_thread, NULL);
 		if (ret)
 			IPN3KE_AFU_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b5371568b5..33c82474ad 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4156,7 +4156,7 @@ ixgbe_dev_setup_link_thread_handler(void *param)
 	u32 speed;
 	bool autoneg = false;
 
-	pthread_detach(pthread_self());
+	rte_thread_detach(rte_thread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index a0ce18ca24..272fdcfb8d 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,7 +516,7 @@ struct ixgbe_adapter {
 	uint8_t pflink_fullchk;
 	uint8_t mac_ctrl_frame_fwd;
 	rte_atomic32_t link_thread_running;
-	pthread_t link_thread_tid;
+	rte_thread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 871d11c413..5026305362 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -3,7 +3,7 @@
  */
 
 #include <fcntl.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <unistd.h>
 
 #include <rte_string_fns.h>
@@ -50,7 +50,7 @@ struct pmd_internals {
 	uint16_t port_id;
 	int is_kni_started;
 
-	pthread_t thread;
+	rte_thread_t thread;
 	int stop_thread;
 	int no_request_thread;
 
@@ -186,11 +186,11 @@ eth_kni_dev_stop(struct rte_eth_dev *dev)
 	if (internals->no_request_thread == 0 && internals->stop_thread == 0) {
 		internals->stop_thread = 1;
 
-		ret = pthread_cancel(internals->thread);
+		ret = rte_thread_cancel(internals->thread);
 		if (ret)
 			PMD_LOG(ERR, "Can't cancel the thread");
 
-		ret = pthread_join(internals->thread, NULL);
+		ret = rte_thread_join(internals->thread, NULL);
 		if (ret)
 			PMD_LOG(ERR, "Can't join the thread");
 	}
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 534a56a555..15080bbc1c 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -2557,7 +2557,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 
 	sh->numa_node = spawn->pci_dev->device.numa_node;
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP"
 	 * before the device creation. The rdma_core library
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index cf1815cb74..5858659183 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -183,7 +183,7 @@ int mlx5_logtype;
 
 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 						LIST_HEAD_INITIALIZER();
-static pthread_mutex_t mlx5_dev_ctx_list_mutex;
+static rte_thread_mutex_t mlx5_dev_ctx_list_mutex;
 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	[MLX5_IPOOL_DECAP_ENCAP] = {
@@ -1088,7 +1088,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	MLX5_ASSERT(spawn);
 	/* Secondary process should not create the shared context. */
 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
@@ -1215,11 +1215,11 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next);
 	rte_spinlock_init(&sh->geneve_tlv_opt_sl);
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	return sh;
 error:
-	pthread_mutex_destroy(&sh->txpp.mutex);
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	MLX5_ASSERT(sh);
 	if (sh->cnt_id_tbl)
 		mlx5_l3t_destroy(sh->cnt_id_tbl);
@@ -1251,7 +1251,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 void
 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 {
-	pthread_mutex_lock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_lock(&mlx5_dev_ctx_list_mutex);
 #ifdef RTE_LIBRTE_MLX5_DEBUG
 	/* Check the object presence in the list. */
 	struct mlx5_dev_ctx_shared *lctx;
@@ -1282,7 +1282,7 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	/* Release flow workspaces objects on the last device. */
 	if (LIST_EMPTY(&mlx5_dev_ctx_list))
 		mlx5_flow_os_release_workspace();
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 	/*
 	 *  Ensure there is no async event handler installed.
 	 *  Only primary process handles async device events.
@@ -1315,11 +1315,11 @@ mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh)
 	if (sh->ctx)
 		claim_zero(mlx5_glue->close_device(sh->ctx));
 	MLX5_ASSERT(sh->geneve_tlv_option_resource == NULL);
-	pthread_mutex_destroy(&sh->txpp.mutex);
+	rte_thread_mutex_destroy(&sh->txpp.mutex);
 	mlx5_free(sh);
 	return;
 exit:
-	pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
+	rte_thread_mutex_unlock(&mlx5_dev_ctx_list_mutex);
 }
 
 /**
@@ -2450,7 +2450,7 @@ RTE_LOG_REGISTER_DEFAULT(mlx5_logtype, NOTICE)
  */
 RTE_INIT(rte_mlx5_pmd_init)
 {
-	pthread_mutex_init(&mlx5_dev_ctx_list_mutex, NULL);
+	rte_thread_mutex_init(&mlx5_dev_ctx_list_mutex);
 	mlx5_common_init();
 	/* Build the static tables for Verbs conversion. */
 	mlx5_set_ptype_table();
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 32b2817bf2..74df9f4355 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -949,7 +949,7 @@ struct mlx5_txpp_ts {
 
 /* Tx packet pacing structure. */
 struct mlx5_dev_txpp {
-	pthread_mutex_t mutex; /* Pacing create/destroy mutex. */
+	rte_thread_mutex_t mutex; /* Pacing create/destroy mutex. */
 	uint32_t refcnt; /* Pacing reference counter. */
 	uint32_t freq; /* Timestamp frequency, Hz. */
 	uint32_t tick; /* Completion tick duration in nanoseconds. */
diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c
index d90399afb5..e308c5e599 100644
--- a/drivers/net/mlx5/mlx5_txpp.c
+++ b/drivers/net/mlx5/mlx5_txpp.c
@@ -905,7 +905,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 		if (ret < 0)
 			return 0;
 	}
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	if (sh->txpp.refcnt) {
@@ -921,7 +921,7 @@ mlx5_txpp_start(struct rte_eth_dev *dev)
 			rte_errno = -err;
 		}
 	}
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	return err;
@@ -948,7 +948,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	}
 	priv->txpp_en = 0;
-	ret = pthread_mutex_lock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_lock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 	MLX5_ASSERT(sh->txpp.refcnt);
@@ -956,7 +956,7 @@ mlx5_txpp_stop(struct rte_eth_dev *dev)
 		return;
 	/* No references any more, do actual destroy. */
 	mlx5_txpp_destroy(sh);
-	ret = pthread_mutex_unlock(&sh->txpp.mutex);
+	ret = rte_thread_mutex_unlock(&sh->txpp.mutex);
 	MLX5_ASSERT(!ret);
 	RTE_SET_USED(ret);
 }
diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c
index c4d5790726..229bad3ea7 100644
--- a/drivers/net/mlx5/windows/mlx5_flow_os.c
+++ b/drivers/net/mlx5/windows/mlx5_flow_os.c
@@ -253,7 +253,7 @@ struct mlx5_workspace_thread {
 static struct mlx5_workspace_thread *curr;
 static struct mlx5_workspace_thread *first;
 rte_thread_key ws_tls_index;
-static pthread_mutex_t lock_thread_list;
+static rte_thread_mutex_t lock_thread_list;
 
 static bool
 mlx5_is_thread_alive(HANDLE thread_handle)
@@ -330,7 +330,7 @@ mlx5_flow_os_release_workspace(void)
 		free(first);
 	}
 	rte_thread_key_delete(ws_tls_index);
-	pthread_mutex_destroy(&lock_thread_list);
+	rte_thread_mutex_destroy(&lock_thread_list);
 }
 
 static int
@@ -352,7 +352,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 	}
 	temp->mlx5_ws = data;
 	temp->thread_handle = curr_thread;
-	pthread_mutex_lock(&lock_thread_list);
+	rte_thread_mutex_lock(&lock_thread_list);
 	mlx5_clear_thread_list();
 	if (!first) {
 		first = temp;
@@ -361,7 +361,7 @@ mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data)
 		curr->next = temp;
 		curr = curr->next;
 	}
-	pthread_mutex_unlock(&lock_thread_list);
+	rte_thread_mutex_unlock(&lock_thread_list);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ mlx5_flow_os_init_workspace_once(void)
 		DRV_LOG(ERR, "Can't create flow workspace data thread key.");
 		return err;
 	}
-	pthread_mutex_init(&lock_thread_list, NULL);
+	rte_thread_mutex_init(&lock_thread_list);
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 3fe3f55f49..e37e16d70f 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -228,7 +228,7 @@ mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
 	int err = 0;
 	struct mlx5_context *mlx5_ctx;
 
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
+	rte_thread_mutex_init(&sh->txpp.mutex);
 	/* Set numa node from pci probe */
 	sh->numa_node = spawn->pci_dev->device.numa_node;
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index c5b5399282..f0cb71c93d 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -153,10 +153,10 @@ void osal_dma_free_mem(struct ecore_dev *edev, dma_addr_t phys);
 
 /* Mutexes */
 
-typedef pthread_mutex_t osal_mutex_t;
-#define OSAL_MUTEX_RELEASE(lock) pthread_mutex_unlock(lock)
-#define OSAL_MUTEX_INIT(lock) pthread_mutex_init(lock, NULL)
-#define OSAL_MUTEX_ACQUIRE(lock) pthread_mutex_lock(lock)
+typedef rte_thread_mutex_t osal_mutex_t;
+#define OSAL_MUTEX_RELEASE(lock) rte_thread_mutex_unlock(lock)
+#define OSAL_MUTEX_INIT(lock) rte_thread_mutex_init(lock)
+#define OSAL_MUTEX_ACQUIRE(lock) rte_thread_mutex_lock(lock)
 #define OSAL_MUTEX_ALLOC(hwfn, lock) nothing
 #define OSAL_MUTEX_DEALLOC(lock) nothing
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a202931e9a..cbab53fb51 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -3,7 +3,7 @@
  * Copyright(c) 2016-2018 Intel Corporation
  */
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <stdbool.h>
 #include <sys/epoll.h>
 
@@ -121,7 +121,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
@@ -507,7 +507,7 @@ find_internal_resource(char *ifname)
 	if (ifname == NULL)
 		return NULL;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		internal = list->eth_dev->data->dev_private;
@@ -517,7 +517,7 @@ find_internal_resource(char *ifname)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -1001,9 +1001,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 		goto free_list;
 
 	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
@@ -1035,9 +1035,9 @@ vhost_driver_setup(struct rte_eth_dev *eth_dev)
 	rte_vhost_driver_unregister(internal->iface_name);
 list_remove:
 	vring_states[eth_dev->data->port_id] = NULL;
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 	rte_free(vring_state);
 free_list:
 	rte_free(list);
@@ -1093,7 +1093,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	if (!rte_eth_dev_is_valid_port(port_id))
 		return -1;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		eth_dev = list->eth_dev;
@@ -1106,7 +1106,7 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	return vid;
 }
@@ -1184,9 +1184,9 @@ eth_dev_close(struct rte_eth_dev *dev)
 	list = find_internal_resource(internal->iface_name);
 	if (list) {
 		rte_vhost_driver_unregister(internal->iface_name);
-		pthread_mutex_lock(&internal_list_lock);
+		rte_thread_mutex_lock(&internal_list_lock);
 		TAILQ_REMOVE(&internal_list, list, next);
-		pthread_mutex_unlock(&internal_list_lock);
+		rte_thread_mutex_unlock(&internal_list_lock);
 		rte_free(list);
 	}
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index 364f43e21c..9231da676b 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -143,7 +143,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 	uint64_t features;
 	int ret = -1;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 0: tell vhost to create queues */
 	if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
@@ -161,7 +161,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev)
 		goto error;
 	PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return ret;
 }
@@ -185,7 +185,7 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 	 * memory subsystem in the future.
 	 */
 	rte_mcfg_mem_read_lock();
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	/* Step 2: share memory regions */
 	ret = dev->ops->set_memory_table(dev);
@@ -206,12 +206,12 @@ virtio_user_start_device(struct virtio_user_dev *dev)
 
 	dev->started = true;
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	return 0;
 error:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	rte_mcfg_mem_read_unlock();
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
@@ -226,7 +226,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	uint32_t i;
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	if (!dev->started)
 		goto out;
 
@@ -249,11 +249,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
 	dev->started = false;
 
 out:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	return 0;
 err:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
 
@@ -380,7 +380,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	if (msl->external)
 		return;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	if (dev->started == false)
 		goto exit;
@@ -405,7 +405,7 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
 	}
 
 exit:
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 
 	if (ret < 0)
 		PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
@@ -491,7 +491,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
 	uint64_t backend_features;
 	int i;
 
-	pthread_mutex_init(&dev->mutex, NULL);
+	rte_thread_mutex_init(&dev->mutex);
 	strlcpy(dev->path, path, PATH_MAX);
 
 	for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; i++) {
@@ -796,13 +796,13 @@ virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
 {
 	int ret;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 	dev->status = status;
 	ret = dev->ops->set_status(dev, status);
 	if (ret && ret != -ENOTSUP)
 		PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
@@ -812,7 +812,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 	int ret;
 	uint8_t status;
 
-	pthread_mutex_lock(&dev->mutex);
+	rte_thread_mutex_lock(&dev->mutex);
 
 	ret = dev->ops->get_status(dev, &status);
 	if (!ret) {
@@ -837,7 +837,7 @@ virtio_user_dev_update_status(struct virtio_user_dev *dev)
 		PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
 	}
 
-	pthread_mutex_unlock(&dev->mutex);
+	rte_thread_mutex_unlock(&dev->mutex);
 	return ret;
 }
 
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 58ad5198b6..8c2df84d74 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -55,7 +55,7 @@ struct virtio_user_dev {
 	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
-	pthread_mutex_t	mutex;
+	rte_thread_mutex_t	mutex;
 	bool		started;
 
 	void *backend_data;
diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 76e6a8530b..5afedf4d05 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -69,7 +69,7 @@ static const struct rte_pci_id pci_ifpga_map[] = {
 static struct ifpga_rawdev ifpga_rawdevices[IFPGA_RAWDEV_NUM];
 
 static int ifpga_monitor_start;
-static pthread_t ifpga_monitor_start_thread;
+static rte_thread_t ifpga_monitor_start_thread;
 
 #define IFPGA_MAX_IRQ 12
 /* 0 for FME interrupt, others are reserved for AFU irq */
@@ -545,11 +545,11 @@ ifpga_monitor_stop_func(void)
 	int ret;
 
 	if (ifpga_monitor_start == 1) {
-		ret = pthread_cancel(ifpga_monitor_start_thread);
+		ret = rte_thread_cancel(ifpga_monitor_start_thread);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't cancel the thread");
 
-		ret = pthread_join(ifpga_monitor_start_thread, NULL);
+		ret = rte_thread_join(ifpga_monitor_start_thread, NULL);
 		if (ret)
 			IFPGA_RAWDEV_PMD_ERR("Can't join the thread");
 
diff --git a/drivers/vdpa/ifc/ifcvf_vdpa.c b/drivers/vdpa/ifc/ifcvf_vdpa.c
index 1dc813d0a3..7a90237ba2 100644
--- a/drivers/vdpa/ifc/ifcvf_vdpa.c
+++ b/drivers/vdpa/ifc/ifcvf_vdpa.c
@@ -3,7 +3,7 @@
  */
 
 #include <unistd.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/ioctl.h>
@@ -52,7 +52,7 @@ struct ifcvf_internal {
 	int vfio_container_fd;
 	int vfio_group_fd;
 	int vfio_dev_fd;
-	pthread_t tid;	/* thread for notify relay */
+	rte_thread_t tid;	/* thread for notify relay */
 	int epfd;
 	int vid;
 	struct rte_vdpa_device *vdev;
@@ -79,7 +79,7 @@ TAILQ_HEAD(internal_list_head, internal_list);
 static struct internal_list_head internal_list =
 	TAILQ_HEAD_INITIALIZER(internal_list);
 
-static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t internal_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static void update_used_ring(struct ifcvf_internal *internal, uint16_t qid);
 
@@ -89,7 +89,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (vdev == list->internal->vdev) {
@@ -98,7 +98,7 @@ find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -112,7 +112,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 	int found = 0;
 	struct internal_list *list;
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 
 	TAILQ_FOREACH(list, &internal_list, next) {
 		if (!rte_pci_addr_cmp(&pdev->addr,
@@ -122,7 +122,7 @@ find_internal_resource_by_dev(struct rte_pci_device *pdev)
 		}
 	}
 
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	if (!found)
 		return NULL;
@@ -503,7 +503,7 @@ setup_notify_relay(struct ifcvf_internal *internal)
 	ret = rte_ctrl_thread_create(&internal->tid, name, NULL, notify_relay,
 				     (void *)internal);
 	if (ret != 0) {
-		DRV_LOG(ERR, "failed to create notify relay pthread.");
+		DRV_LOG(ERR, "failed to create notify relay thread.");
 		return -1;
 	}
 
@@ -513,13 +513,11 @@ setup_notify_relay(struct ifcvf_internal *internal)
 static int
 unset_notify_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
-	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+	if (internal->tid.opaque_id) {
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
-	internal->tid = 0;
+	internal->tid.opaque_id = 0;
 
 	if (internal->epfd >= 0)
 		close(internal->epfd);
@@ -809,7 +807,7 @@ setup_vring_relay(struct ifcvf_internal *internal)
 	ret = rte_ctrl_thread_create(&internal->tid, name, NULL, vring_relay,
 				     (void *)internal);
 	if (ret != 0) {
-		DRV_LOG(ERR, "failed to create ring relay pthread.");
+		DRV_LOG(ERR, "failed to create ring relay thread.");
 		return -1;
 	}
 
@@ -819,13 +817,11 @@ setup_vring_relay(struct ifcvf_internal *internal)
 static int
 unset_vring_relay(struct ifcvf_internal *internal)
 {
-	void *status;
-
-	if (internal->tid) {
-		pthread_cancel(internal->tid);
-		pthread_join(internal->tid, &status);
+	if (internal->tid.opaque_id) {
+		rte_thread_cancel(internal->tid);
+		rte_thread_join(internal->tid, NULL);
 	}
-	internal->tid = 0;
+	internal->tid.opaque_id = 0;
 
 	if (internal->epfd >= 0)
 		close(internal->epfd);
@@ -1253,9 +1249,9 @@ ifcvf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		goto error;
 	}
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_atomic32_set(&internal->started, 1);
 	update_datapath(internal);
@@ -1293,9 +1289,9 @@ ifcvf_pci_remove(struct rte_pci_device *pci_dev)
 	rte_vfio_container_destroy(internal->vfio_container_fd);
 	rte_vdpa_unregister_device(internal->vdev);
 
-	pthread_mutex_lock(&internal_list_lock);
+	rte_thread_mutex_lock(&internal_list_lock);
 	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
+	rte_thread_mutex_unlock(&internal_list_lock);
 
 	rte_free(list);
 	rte_free(internal);
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index e5e03e6582..e7f4acb48d 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -48,7 +48,7 @@
 
 TAILQ_HEAD(mlx5_vdpa_privs, mlx5_vdpa_priv) priv_list =
 					      TAILQ_HEAD_INITIALIZER(priv_list);
-static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t priv_list_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 static struct mlx5_vdpa_priv *
 mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
@@ -56,14 +56,14 @@ mlx5_vdpa_find_priv_resource_by_vdev(struct rte_vdpa_device *vdev)
 	struct mlx5_vdpa_priv *priv;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (vdev == priv->vdev) {
 			found = 1;
 			break;
 		}
 	}
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (!found) {
 		DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name);
 		rte_errno = EINVAL;
@@ -143,9 +143,9 @@ mlx5_vdpa_set_vring_state(int vid, int vring, int state)
 		DRV_LOG(ERR, "Too big vring id: %d.", vring);
 		return -E2BIG;
 	}
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	ret = mlx5_vdpa_virtq_enable(priv, vring, state);
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 	return ret;
 }
 
@@ -296,7 +296,7 @@ mlx5_vdpa_dev_close(int vid)
 	priv->configured = 0;
 	priv->vid = 0;
 	/* The mutex may stay locked after event thread cancel - initiate it. */
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
+	rte_thread_mutex_init(&priv->vq_config_lock);
 	DRV_LOG(INFO, "vDPA device %d was closed.", vid);
 	return ret;
 }
@@ -736,10 +736,10 @@ mlx5_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	mlx5_vdpa_config_get(pci_dev->device.devargs, priv);
 	SLIST_INIT(&priv->mr_list);
-	pthread_mutex_init(&priv->vq_config_lock, NULL);
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_init(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_INSERT_TAIL(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	return 0;
 
 error:
@@ -770,7 +770,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	struct mlx5_vdpa_priv *priv = NULL;
 	int found = 0;
 
-	pthread_mutex_lock(&priv_list_lock);
+	rte_thread_mutex_lock(&priv_list_lock);
 	TAILQ_FOREACH(priv, &priv_list, next) {
 		if (!rte_pci_addr_cmp(&priv->pci_dev->addr, &pci_dev->addr)) {
 			found = 1;
@@ -779,7 +779,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 	}
 	if (found)
 		TAILQ_REMOVE(&priv_list, priv, next);
-	pthread_mutex_unlock(&priv_list_lock);
+	rte_thread_mutex_unlock(&priv_list_lock);
 	if (found) {
 		if (priv->configured)
 			mlx5_vdpa_dev_close(priv->vid);
@@ -790,7 +790,7 @@ mlx5_vdpa_pci_remove(struct rte_pci_device *pci_dev)
 		if (priv->vdev)
 			rte_vdpa_unregister_device(priv->vdev);
 		mlx5_glue->close_device(priv->ctx);
-		pthread_mutex_destroy(&priv->vq_config_lock);
+		rte_thread_mutex_destroy(&priv->vq_config_lock);
 		rte_free(priv);
 	}
 	return 0;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h
index 722c72b65e..cf7df473f8 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h
@@ -119,9 +119,9 @@ enum {
 struct mlx5_vdpa_priv {
 	TAILQ_ENTRY(mlx5_vdpa_priv) next;
 	uint8_t configured;
-	pthread_mutex_t vq_config_lock;
+	rte_thread_mutex_t vq_config_lock;
 	uint64_t no_traffic_counter;
-	pthread_t timer_tid;
+	rte_thread_t timer_tid;
 	int event_mode;
 	int event_core; /* Event thread cpu affinity core. */
 	uint32_t event_us;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
index 88f6a4256d..b3639659f6 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c
@@ -285,7 +285,7 @@ mlx5_vdpa_event_handle(void *arg)
 	case MLX5_VDPA_EVENT_MODE_FIXED_TIMER:
 		priv->timer_delay_us = priv->event_us;
 		while (1) {
-			pthread_mutex_lock(&priv->vq_config_lock);
+			rte_thread_mutex_lock(&priv->vq_config_lock);
 			max = mlx5_vdpa_queues_complete(priv);
 			if (max == 0 && priv->no_traffic_counter++ >=
 			    priv->no_traffic_max) {
@@ -293,10 +293,10 @@ mlx5_vdpa_event_handle(void *arg)
 					priv->vdev->device->name);
 				mlx5_vdpa_arm_all_cqs(priv);
 				do {
-					pthread_mutex_unlock
+					rte_thread_mutex_unlock
 							(&priv->vq_config_lock);
 					cq = mlx5_vdpa_event_wait(priv);
-					pthread_mutex_lock
+					rte_thread_mutex_lock
 							(&priv->vq_config_lock);
 					if (cq == NULL ||
 					       mlx5_vdpa_queue_complete(cq) > 0)
@@ -307,7 +307,7 @@ mlx5_vdpa_event_handle(void *arg)
 			} else if (max != 0) {
 				priv->no_traffic_counter = 0;
 			}
-			pthread_mutex_unlock(&priv->vq_config_lock);
+			rte_thread_mutex_unlock(&priv->vq_config_lock);
 			mlx5_vdpa_timer_sleep(priv, max);
 		}
 		return NULL;
@@ -315,10 +315,10 @@ mlx5_vdpa_event_handle(void *arg)
 		do {
 			cq = mlx5_vdpa_event_wait(priv);
 			if (cq != NULL) {
-				pthread_mutex_lock(&priv->vq_config_lock);
+				rte_thread_mutex_lock(&priv->vq_config_lock);
 				if (mlx5_vdpa_queue_complete(cq) > 0)
 					mlx5_vdpa_cq_arm(priv, cq);
-				pthread_mutex_unlock(&priv->vq_config_lock);
+				rte_thread_mutex_unlock(&priv->vq_config_lock);
 			}
 		} while (1);
 		return NULL;
@@ -340,7 +340,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 	struct mlx5_vdpa_virtq *virtq;
 	uint64_t sec;
 
-	pthread_mutex_lock(&priv->vq_config_lock);
+	rte_thread_mutex_lock(&priv->vq_config_lock);
 	while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,
 					 sizeof(out.buf)) >=
 				       (ssize_t)sizeof(out.event_resp.cookie)) {
@@ -386,7 +386,7 @@ mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)
 			virtq->err_time[i - 1] = virtq->err_time[i];
 		virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();
 	}
-	pthread_mutex_unlock(&priv->vq_config_lock);
+	rte_thread_mutex_unlock(&priv->vq_config_lock);
 #endif
 }
 
@@ -473,27 +473,25 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 {
 	int ret;
 	rte_cpuset_t cpuset;
-	pthread_attr_t attr;
+	rte_thread_attr_t attr;
 	char name[16];
-	const struct sched_param sp = {
-		.sched_priority = sched_get_priority_max(SCHED_RR),
-	};
 
 	if (!priv->eventc)
 		/* All virtqs are in poll mode. */
 		return 0;
-	pthread_attr_init(&attr);
-	ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+
+	ret = rte_thread_attr_init(&attr);
 	if (ret) {
-		DRV_LOG(ERR, "Failed to set thread sched policy = RR.");
+		DRV_LOG(ERR, "Failed to initialize thread attributes");
 		return -1;
 	}
-	ret = pthread_attr_setschedparam(&attr, &sp);
+	ret = rte_thread_attr_set_priority(&attr,
+			RTE_THREAD_PRIORITY_REALTIME_CRITICAL);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to set thread priority.");
 		return -1;
 	}
-	ret = pthread_create(&priv->timer_tid, &attr, mlx5_vdpa_event_handle,
+	ret = rte_thread_create(&priv->timer_tid, &attr, mlx5_vdpa_event_handle,
 			     (void *)priv);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to create timer thread.");
@@ -504,13 +502,13 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 		CPU_SET(priv->event_core, &cpuset);
 	else
 		cpuset = rte_lcore_cpuset(rte_get_main_lcore());
-	ret = pthread_setaffinity_np(priv->timer_tid, sizeof(cpuset), &cpuset);
+	ret = rte_thread_set_affinity_by_id(priv->timer_tid, &cpuset);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to set thread affinity.");
 		return -1;
 	}
 	snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid);
-	ret = rte_thread_setname(priv->timer_tid, name);
+	ret = pthread_setname_np(priv->timer_tid.opaque_id, name);
 	if (ret)
 		DRV_LOG(DEBUG, "Cannot set timer thread name.");
 	return 0;
@@ -519,13 +517,11 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)
 void
 mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv)
 {
-	void *status;
-
-	if (priv->timer_tid) {
-		pthread_cancel(priv->timer_tid);
-		pthread_join(priv->timer_tid, &status);
+	if (priv->timer_tid.opaque_id) {
+		rte_thread_cancel(priv->timer_tid);
+		rte_thread_join(priv->timer_tid, NULL);
 	}
-	priv->timer_tid = 0;
+	priv->timer_tid.opaque_id = 0;
 }
 
 void
diff --git a/examples/kni/main.c b/examples/kni/main.c
index beabb3c848..e4741f85ba 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -1042,8 +1042,8 @@ main(int argc, char** argv)
 	int ret;
 	uint16_t nb_sys_ports, port;
 	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
+	int retval;
+	rte_thread_t kni_link_tid;
 	int pid;
 
 	/* Associate signal_hanlder function with USR signals */
@@ -1126,7 +1126,7 @@ main(int argc, char** argv)
 			return -1;
 	}
 	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
+	rte_thread_join(kni_link_tid, &retval);
 
 	/* Release resources */
 	RTE_ETH_FOREACH_DEV(port) {
diff --git a/examples/performance-thread/pthread_shim/main.c b/examples/performance-thread/pthread_shim/main.c
index 257de50692..bef7b59842 100644
--- a/examples/performance-thread/pthread_shim/main.c
+++ b/examples/performance-thread/pthread_shim/main.c
@@ -164,7 +164,7 @@ static void *initial_lthread(void *args __rte_unused)
 			rte_exit(EXIT_FAILURE, "Cannot create helloworld thread\n");
 
 		snprintf(name, sizeof(name), "helloworld-%u", (uint32_t)i);
-		rte_thread_setname(tid[i], name);
+		pthread_setname_np(tid[i], name);
 	}
 
 	/* wait for 1s to allow threads
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index d2179eadb9..4d02502602 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1634,7 +1634,7 @@ main(int argc, char *argv[])
 	unsigned nb_ports, valid_num_ports;
 	int ret, i;
 	uint16_t portid;
-	static pthread_t tid;
+	static rte_thread_t tid;
 	uint64_t flags = RTE_VHOST_USER_NET_COMPLIANT_OL_FLAGS;
 
 	signal(SIGINT, sigint_handler);
diff --git a/examples/vhost_blk/vhost_blk.c b/examples/vhost_blk/vhost_blk.c
index fe2b4e4803..5b31d58ac2 100644
--- a/examples/vhost_blk/vhost_blk.c
+++ b/examples/vhost_blk/vhost_blk.c
@@ -5,7 +5,7 @@
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 #endif
-#include <pthread.h>
+#include <rte_thread.h>
 #include <sched.h>
 
 #include <stdint.h>
@@ -533,7 +533,7 @@ ctrlr_worker(void *arg)
 {
 	struct vhost_blk_ctrlr *ctrlr = (struct vhost_blk_ctrlr *)arg;
 	cpu_set_t cpuset;
-	pthread_t thread;
+	rte_thread_t thread;
 	int i;
 
 	fprintf(stdout, "Ctrlr Worker Thread start\n");
@@ -545,10 +545,10 @@ ctrlr_worker(void *arg)
 		exit(0);
 	}
 
-	thread = pthread_self();
+	thread = rte_thread_self();
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
-	pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+	rte_thread_set_affinity_by_id(thread, &cpuset);
 
 	for (i = 0; i < NUM_OF_BLK_QUEUES; i++)
 		submit_inflight_vq(&ctrlr->queues[i]);
@@ -604,7 +604,7 @@ new_device(int vid)
 	struct vhost_blk_queue *vq;
 	char path[PATH_MAX];
 	uint64_t features, protocol_features;
-	pthread_t tid;
+	rte_thread_t tid;
 	int i, ret;
 	bool packed_ring, inflight_shmfd;
 
@@ -693,7 +693,7 @@ new_device(int vid)
 
 	/* device has been started */
 	ctrlr->started = 1;
-	pthread_detach(tid);
+	rte_thread_detach(tid);
 	return 0;
 }
 
diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index 9d29696b84..1f6aba498c 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -1872,8 +1872,7 @@ eal_auto_detect_cores(struct rte_config *cfg)
 	unsigned int removed = 0;
 	rte_cpuset_t affinity_set;
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&affinity_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &affinity_set))
 		CPU_ZERO(&affinity_set);
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
@@ -1901,8 +1900,7 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 	}
 	RTE_CPU_NOT(cpuset, cpuset);
 
-	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
-				&default_set))
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &default_set))
 		CPU_ZERO(&default_set);
 
 	RTE_CPU_AND(cpuset, cpuset, &default_set);
diff --git a/lib/eal/common/eal_common_proc.c b/lib/eal/common/eal_common_proc.c
index dc4a2efa82..e8a93ee829 100644
--- a/lib/eal/common/eal_common_proc.c
+++ b/lib/eal/common/eal_common_proc.c
@@ -37,7 +37,7 @@
 static int mp_fd = -1;
 static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
 static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
-static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
+static rte_thread_mutex_t mp_mutex_action = RTE_THREAD_MUTEX_INITIALIZER;
 static char peer_name[PATH_MAX];
 
 struct action_entry {
@@ -96,10 +96,10 @@ TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
 	struct pending_request_list requests;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } pending_requests = {
 	.requests = TAILQ_HEAD_INITIALIZER(pending_requests.requests),
-	.lock = PTHREAD_MUTEX_INITIALIZER,
+	.lock = RTE_THREAD_MUTEX_INITIALIZER,
 	/**< used in async requests only */
 };
 
@@ -222,15 +222,15 @@ rte_mp_action_register(const char *name, rte_mp_t action)
 	strlcpy(entry->action_name, name, sizeof(entry->action_name));
 	entry->action = action;
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	if (find_action_entry_by_name(name) != NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		rte_errno = EEXIST;
 		free(entry);
 		return -1;
 	}
 	TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	return 0;
 }
 
@@ -249,14 +249,14 @@ rte_mp_action_unregister(const char *name)
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(name);
 	if (entry == NULL) {
-		pthread_mutex_unlock(&mp_mutex_action);
+		rte_thread_mutex_unlock(&mp_mutex_action);
 		return;
 	}
 	TAILQ_REMOVE(&action_entry_list, entry, next);
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 	free(entry);
 }
 
@@ -328,7 +328,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 	if (m->type == MP_REP || m->type == MP_IGN) {
 		struct pending_request *req = NULL;
 
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		pending_req = find_pending_request(s->sun_path, msg->name);
 		if (pending_req) {
 			memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -343,18 +343,18 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 						pending_req);
 		} else
 			RTE_LOG(ERR, EAL, "Drop mp reply: %s\n", msg->name);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		if (req != NULL)
 			trigger_async_action(req);
 		return;
 	}
 
-	pthread_mutex_lock(&mp_mutex_action);
+	rte_thread_mutex_lock(&mp_mutex_action);
 	entry = find_action_entry_by_name(msg->name);
 	if (entry != NULL)
 		action = entry->action;
-	pthread_mutex_unlock(&mp_mutex_action);
+	rte_thread_mutex_unlock(&mp_mutex_action);
 
 	if (!action) {
 		if (m->type == MP_REQ && !internal_conf->init_complete) {
@@ -524,9 +524,9 @@ async_reply_handle(void *arg)
 {
 	struct pending_request *req;
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	req = async_reply_handle_thread_unsafe(arg);
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	if (req != NULL)
 		trigger_async_action(req);
@@ -584,7 +584,7 @@ rte_mp_channel_init(void)
 {
 	char path[PATH_MAX];
 	int dir_fd;
-	pthread_t mp_handle_tid;
+	rte_thread_t mp_handle_tid;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
@@ -998,9 +998,9 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	/* for secondary process, send request to the primary process only */
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-		pthread_mutex_lock(&pending_requests.lock);
+		rte_thread_mutex_lock(&pending_requests.lock);
 		ret = mp_request_sync(eal_mp_socket_path(), req, reply, &end);
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 		goto end;
 	}
 
@@ -1021,7 +1021,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 		goto close_end;
 	}
 
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
 		char path[PATH_MAX];
 
@@ -1040,7 +1040,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 	ret = 0;
 
 unlock_end:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
 
@@ -1118,7 +1118,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * of requests to the queue at once, and some of the replies may arrive
 	 * before we add all of the requests to the queue.
 	 */
-	pthread_mutex_lock(&pending_requests.lock);
+	rte_thread_mutex_lock(&pending_requests.lock);
 
 	/* we have to ensure that callback gets triggered even if we don't send
 	 * anything, therefore earlier we have allocated a dummy request. fill
@@ -1141,7 +1141,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 			dummy_used = true;
 		}
 
-		pthread_mutex_unlock(&pending_requests.lock);
+		rte_thread_mutex_unlock(&pending_requests.lock);
 
 		/* if we couldn't send anything, clean up */
 		if (ret != 0)
@@ -1185,7 +1185,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	/* finally, unlock the queue */
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 
 	/* unlock the directory */
 	flock(dir_fd, LOCK_UN);
@@ -1201,7 +1201,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 closedir_fail:
 	closedir(mp_dir);
 unlock_fail:
-	pthread_mutex_unlock(&pending_requests.lock);
+	rte_thread_mutex_unlock(&pending_requests.lock);
 fail:
 	free(dummy);
 	free(param);
diff --git a/lib/eal/common/eal_common_thread.c b/lib/eal/common/eal_common_thread.c
index 1a52f42a2b..d46ab8cf77 100644
--- a/lib/eal/common/eal_common_thread.c
+++ b/lib/eal/common/eal_common_thread.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <signal.h>
 #include <sched.h>
 #include <assert.h>
@@ -86,9 +85,8 @@ thread_update_affinity(rte_cpuset_t *cpusetp)
 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");
+	if (rte_thread_set_affinity_by_id(rte_thread_self(), cpusetp) != 0) {
+		RTE_LOG(ERR, EAL, "rte_thread_set_affinity failed\n");
 		return -1;
 	}
 
@@ -169,14 +167,14 @@ __rte_thread_uninit(void)
 struct rte_thread_ctrl_params {
 	void *(*start_routine)(void *);
 	void *arg;
-	pthread_barrier_t configured;
+	rte_thread_barrier_t configured;
 	unsigned int refcnt;
 };
 
 static void ctrl_params_free(struct rte_thread_ctrl_params *params)
 {
 	if (__atomic_sub_fetch(&params->refcnt, 1, __ATOMIC_ACQ_REL) == 0) {
-		(void)pthread_barrier_destroy(&params->configured);
+		(void)rte_thread_barrier_destroy(&params->configured);
 		free(params);
 	}
 }
@@ -192,7 +190,7 @@ static void *ctrl_thread_init(void *arg)
 
 	__rte_thread_init(rte_lcore_id(), cpuset);
 
-	pthread_barrier_wait(&params->configured);
+	rte_thread_barrier_wait(&params->configured);
 	start_routine = params->start_routine;
 	ctrl_params_free(params);
 
@@ -203,8 +201,8 @@ static void *ctrl_thread_init(void *arg)
 }
 
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg)
 {
 	struct internal_config *internal_conf =
@@ -221,11 +219,11 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 	params->arg = arg;
 	params->refcnt = 2;
 
-	ret = pthread_barrier_init(&params->configured, NULL, 2);
+	ret = rte_thread_barrier_init(&params->configured, 2);
 	if (ret != 0)
 		goto fail_no_barrier;
 
-	ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+	ret = rte_thread_create(thread, attr, ctrl_thread_init, (void *)params);
 	if (ret != 0)
 		goto fail_with_barrier;
 
@@ -236,22 +234,22 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name,
 				"Cannot set name for ctrl thread\n");
 	}
 
-	ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+	ret = rte_thread_set_affinity_by_id(*thread, cpuset);
 	if (ret != 0)
 		params->start_routine = NULL;
 
-	pthread_barrier_wait(&params->configured);
+	rte_thread_barrier_wait(&params->configured);
 	ctrl_params_free(params);
 
 	if (ret != 0)
 		/* start_routine has been set to NULL above; */
 		/* ctrl thread will exit immediately */
-		pthread_join(*thread, NULL);
+		rte_thread_join(*thread, NULL);
 
 	return -ret;
 
 fail_with_barrier:
-	(void)pthread_barrier_destroy(&params->configured);
+	(void)rte_thread_barrier_destroy(&params->configured);
 
 fail_no_barrier:
 	free(params);
@@ -276,8 +274,7 @@ rte_thread_register(void)
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
-			&cpuset) != 0)
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0)
 		CPU_ZERO(&cpuset);
 	lcore_id = eal_lcore_non_eal_allocate();
 	if (lcore_id >= RTE_MAX_LCORE)
@@ -304,3 +301,14 @@ rte_thread_unregister(void)
 		RTE_LOG(DEBUG, EAL, "Unregistered non-EAL thread (was lcore %u).\n",
 			lcore_id);
 }
+
+void rte_thread_priority_init(void)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+
+	/* If the user doesn't specify the priority through the command
+	 * line arguments, the default 'normal' value will be used.
+	 */
+	internal_conf->thread_priority = RTE_THREAD_PRIORITY_NORMAL;
+}
diff --git a/lib/eal/common/eal_common_trace.c b/lib/eal/common/eal_common_trace.c
index 24e27387b1..6df4a01277 100644
--- a/lib/eal/common/eal_common_trace.c
+++ b/lib/eal/common/eal_common_trace.c
@@ -359,7 +359,7 @@ __rte_trace_mem_per_thread_alloc(void)
 	/* Store the thread name */
 	char *name = header->stream_header.thread_name;
 	memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
-	rte_thread_getname(pthread_self(), name,
+	rte_thread_getname(rte_thread_self(), name,
 		__RTE_TRACE_EMIT_STRING_LEN_MAX);
 
 	trace->lcore_meta[count].mem = header;
diff --git a/lib/eal/common/eal_private.h b/lib/eal/common/eal_private.h
index 64cf4e81c8..4b95001d7d 100644
--- a/lib/eal/common/eal_private.h
+++ b/lib/eal/common/eal_private.h
@@ -19,7 +19,7 @@
  * Structure storing internal configuration (per-lcore)
  */
 struct lcore_config {
-	pthread_t thread_id;       /**< pthread identifier */
+	rte_thread_t thread_id;       /**< pthread identifier */
 	int pipe_main2worker[2];   /**< communication pipe with main */
 	int pipe_worker2main[2];   /**< communication pipe with main */
 
diff --git a/lib/eal/common/eal_thread.h b/lib/eal/common/eal_thread.h
index 4a49117be8..7b3b884463 100644
--- a/lib/eal/common/eal_thread.h
+++ b/lib/eal/common/eal_thread.h
@@ -58,4 +58,10 @@ eal_thread_dump_affinity(rte_cpuset_t *cpuset, char *str, unsigned int size);
 int
 eal_thread_dump_current_affinity(char *str, unsigned int size);
 
+/**
+ * Set the initial thread priority in the internal configuration
+ * to the default value of RTE_THREAD_PRIORITY_NORMAL.
+ */
+void rte_thread_priority_init(void);
+
 #endif /* EAL_THREAD_H */
diff --git a/lib/eal/common/malloc_mp.c b/lib/eal/common/malloc_mp.c
index 2e597a17a2..2620b00e62 100644
--- a/lib/eal/common/malloc_mp.c
+++ b/lib/eal/common/malloc_mp.c
@@ -75,10 +75,10 @@ struct mp_request {
 TAILQ_HEAD(mp_request_list, mp_request);
 static struct {
 	struct mp_request_list list;
-	pthread_mutex_t lock;
+	rte_thread_mutex_t lock;
 } mp_request_list = {
 	.list = TAILQ_HEAD_INITIALIZER(mp_request_list.list),
-	.lock = PTHREAD_MUTEX_INITIALIZER
+	.lock = RTE_THREAD_MUTEX_INITIALIZER
 };
 
 /**
@@ -301,7 +301,7 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 	int ret;
 
 	/* lock access to request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	/* make sure it's not a dupe */
 	entry = find_request_by_id(m->id);
@@ -387,10 +387,10 @@ handle_request(const struct rte_mp_msg *msg, const void *peer __rte_unused)
 
 		TAILQ_INSERT_TAIL(&mp_request_list.list, entry, next);
 	}
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
@@ -409,7 +409,7 @@ handle_sync_response(const struct rte_mp_msg *request,
 	int i;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(mpreq->id);
 	if (entry == NULL) {
@@ -539,10 +539,10 @@ handle_sync_response(const struct rte_mp_msg *request,
 		goto fail;
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -557,7 +557,7 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	struct mp_request *entry;
 
 	/* lock the request */
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	memset(&msg, 0, sizeof(msg));
 
@@ -588,10 +588,10 @@ handle_rollback_response(const struct rte_mp_msg *request,
 	free(entry->alloc_state.ms);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return 0;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return -1;
 }
 
@@ -603,7 +603,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 			(const struct malloc_mp_req *)msg->param;
 	struct mp_request *entry;
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = find_request_by_id(m->id);
 	if (entry != NULL) {
@@ -616,7 +616,7 @@ handle_response(const struct rte_mp_msg *msg, const void *peer  __rte_unused)
 		pthread_cond_signal(&entry->cond);
 	}
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 
 	return 0;
 }
@@ -706,7 +706,7 @@ request_to_primary(struct malloc_mp_req *user_req)
 	memset(&msg, 0, sizeof(msg));
 	memset(&ts, 0, sizeof(ts));
 
-	pthread_mutex_lock(&mp_request_list.lock);
+	rte_thread_mutex_lock(&mp_request_list.lock);
 
 	entry = malloc(sizeof(*entry));
 	if (entry == NULL) {
@@ -767,10 +767,10 @@ request_to_primary(struct malloc_mp_req *user_req)
 	TAILQ_REMOVE(&mp_request_list.list, entry, next);
 	free(entry);
 
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	return ret;
 fail:
-	pthread_mutex_unlock(&mp_request_list.lock);
+	rte_thread_mutex_unlock(&mp_request_list.lock);
 	free(entry);
 	return -1;
 }
diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/freebsd/eal.c b/lib/eal/freebsd/eal.c
index f4d1676754..ec7fd57e7d 100644
--- a/lib/eal/freebsd/eal.c
+++ b/lib/eal/freebsd/eal.c
@@ -667,7 +667,7 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
@@ -676,6 +676,8 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	rte_thread_priority_init();
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -690,7 +692,7 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -854,7 +856,14 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -865,10 +874,25 @@ rte_eal_init(int argc, char **argv)
 
 	ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
 
-	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (tid=%p;cpuset=[%s%s])\n",
-		config->main_lcore, thread_id, cpuset,
+	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (cpuset=[%s%s])\n",
+		config->main_lcore, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -882,8 +906,10 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
+		ret = rte_thread_create(&lcore_config[i].thread_id, &thread_attr,
 				     eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
@@ -893,10 +919,6 @@ rte_eal_init(int argc, char **argv)
 				"lcore-worker-%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/eal/freebsd/eal_alarm.c b/lib/eal/freebsd/eal_alarm.c
index c38b2e04f8..e5d7b130b1 100644
--- a/lib/eal/freebsd/eal_alarm.c
+++ b/lib/eal/freebsd/eal_alarm.c
@@ -37,7 +37,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -156,7 +156,7 @@ eal_alarm_callback(void *arg __rte_unused)
 
 	while (ap != NULL && timespec_cmp(&now, &ap->time) >= 0) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -263,8 +263,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				 * finish. Otherwise we are trying to cancel
 				 * ourselves - mark it by EINPROGRESS.
 				 */
-				if (pthread_equal(ap->executing_id,
-						pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -285,8 +285,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id,
-							 pthread_self()) == 0) {
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0) {
 					executing++;
 				} else {
 					err = EINPROGRESS;
diff --git a/lib/eal/freebsd/eal_interrupts.c b/lib/eal/freebsd/eal_interrupts.c
index 86810845fe..c0bf6c882a 100644
--- a/lib/eal/freebsd/eal_interrupts.c
+++ b/lib/eal/freebsd/eal_interrupts.c
@@ -52,7 +52,7 @@ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static volatile int kq = -1;
 
@@ -737,5 +737,5 @@ rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/eal/freebsd/eal_thread.c b/lib/eal/freebsd/eal_thread.c
index 1dce9b04f2..cb8563cb7a 100644
--- a/lib/eal/freebsd/eal_thread.c
+++ b/lib/eal/freebsd/eal_thread.c
@@ -73,15 +73,15 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id, lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -93,8 +93,8 @@ eal_thread_loop(__rte_unused void *arg)
 	__rte_thread_init(lcore_id, &lcore_config[lcore_id].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 ? "" : "...");
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (cpuset=[%s%s])\n",
+		lcore_id, cpuset, ret == 0 ? "" : "...");
 
 	rte_eal_trace_thread_lcore_ready(lcore_id, cpuset);
 
@@ -143,14 +143,14 @@ int rte_sys_gettid(void)
 	return (int)lwpid;
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	/* this BSD function returns no error */
 	pthread_set_name_np(id, name);
 	return 0;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	RTE_SET_USED(id);
 	RTE_SET_USED(name);
diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index 88a9eba12f..3b872f228f 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -40,6 +40,7 @@ headers += files(
         'rte_string_fns.h',
         'rte_tailq.h',
         'rte_thread.h',
+        'rte_thread_types.h',
         'rte_time.h',
         'rte_trace.h',
         'rte_trace_point.h',
diff --git a/lib/eal/include/rte_lcore.h b/lib/eal/include/rte_lcore.h
index 1550b75da0..d5e004105d 100644
--- a/lib/eal/include/rte_lcore.h
+++ b/lib/eal/include/rte_lcore.h
@@ -374,7 +374,7 @@ rte_lcore_dump(FILE *f);
  * @return
  *   On success, return 0; otherwise return a negative value.
  */
-int rte_thread_setname(pthread_t id, const char *name);
+int rte_thread_setname(rte_thread_t id, const char *name);
 
 /**
  * Get thread name.
@@ -391,7 +391,7 @@ int rte_thread_setname(pthread_t id, const char *name);
  *   On success, return 0; otherwise return a negative value.
  */
 __rte_experimental
-int rte_thread_getname(pthread_t id, char *name, size_t len);
+int rte_thread_getname(rte_thread_t id, char *name, size_t len);
 
 /**
  * Register current non-EAL thread as a lcore.
@@ -440,8 +440,8 @@ rte_thread_unregister(void);
  *   corresponding to the error number.
  */
 int
-rte_ctrl_thread_create(pthread_t *thread, const char *name,
-		const pthread_attr_t *attr,
+rte_ctrl_thread_create(rte_thread_t *thread, const char *name,
+		const rte_thread_attr_t *attr,
 		void *(*start_routine)(void *), void *arg);
 
 #ifdef __cplusplus
diff --git a/lib/eal/include/rte_per_lcore.h b/lib/eal/include/rte_per_lcore.h
index eaedf0cb37..025d97f962 100644
--- a/lib/eal/include/rte_per_lcore.h
+++ b/lib/eal/include/rte_per_lcore.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#include <pthread.h>
-
 /**
  * Macro to define a per lcore variable "var" of type "type", don't
  * use keywords like "static" or "volatile" in type, just prefix the
diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c
index ba19fc6347..70357e099a 100644
--- a/lib/eal/linux/eal.c
+++ b/lib/eal/linux/eal.c
@@ -963,7 +963,6 @@ int
 rte_eal_init(int argc, char **argv)
 {
 	int i, fctret, ret;
-	pthread_t thread_id;
 	static uint32_t run_once;
 	uint32_t has_run = 0;
 	const char *p;
@@ -975,6 +974,8 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	rte_thread_priority_init();
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -991,7 +992,6 @@ rte_eal_init(int argc, char **argv)
 
 	p = strrchr(argv[0], '/');
 	strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
-	thread_id = pthread_self();
 
 	eal_reset_internal_config(internal_conf);
 
@@ -1219,7 +1219,15 @@ rte_eal_init(int argc, char **argv)
 
 	eal_check_mem_on_local_socket();
 
-	if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
 			&lcore_config[config->main_lcore].cpuset) != 0) {
 		rte_eal_init_alert("Cannot set affinity");
 		rte_errno = EINVAL;
@@ -1229,10 +1237,27 @@ rte_eal_init(int argc, char **argv)
 		&lcore_config[config->main_lcore].cpuset);
 
 	ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
-	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (tid=%zx;cpuset=[%s%s])\n",
-		config->main_lcore, (uintptr_t)thread_id, cpuset,
+	RTE_LOG(DEBUG, EAL, "Main lcore %u is ready (cpuset=[%s%s])\n",
+		config->main_lcore, cpuset,
 		ret == 0 ? "" : "...");
 
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot initialize thread attributes,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Cannot set thread priority attribute,"
+			"ret = %d\n", ret);
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -1246,9 +1271,11 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		rte_thread_attr_set_affinity(&thread_attr,
+					     &lcore_config[i].cpuset);
 		/* create a thread for each lcore */
-		ret = pthread_create(&lcore_config[i].thread_id, NULL,
-				     eal_thread_loop, NULL);
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
 		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 
@@ -1260,11 +1287,6 @@ 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/eal/linux/eal_alarm.c b/lib/eal/linux/eal_alarm.c
index 3252c6fa59..fef22a347c 100644
--- a/lib/eal/linux/eal_alarm.c
+++ b/lib/eal/linux/eal_alarm.c
@@ -48,7 +48,7 @@ struct alarm_entry {
 	rte_eal_alarm_callback cb_fn;
 	void *cb_arg;
 	volatile uint8_t executing;
-	volatile pthread_t executing_id;
+	volatile rte_thread_t executing_id;
 };
 
 static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();
@@ -86,7 +86,7 @@ eal_alarm_callback(void *arg __rte_unused)
 			(ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec &&
 						(ap->time.tv_usec * NS_PER_US) <= now.tv_nsec))) {
 		ap->executing = 1;
-		ap->executing_id = pthread_self();
+		ap->executing_id = rte_thread_self();
 		rte_spinlock_unlock(&alarm_list_lk);
 
 		ap->cb_fn(ap->cb_arg);
@@ -207,7 +207,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 				/* If calling from other context, mark that alarm is executing
 				 * so loop can spin till it finish. Otherwise we are trying to
 				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
@@ -228,7 +229,8 @@ rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 					free(ap);
 					count++;
 					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+				} else if (rte_thread_equal(ap->executing_id,
+						rte_thread_self()) == 0)
 					executing++;
 				else
 					err = EINPROGRESS;
diff --git a/lib/eal/linux/eal_interrupts.c b/lib/eal/linux/eal_interrupts.c
index 22b3b7bcd9..e106fa186c 100644
--- a/lib/eal/linux/eal_interrupts.c
+++ b/lib/eal/linux/eal_interrupts.c
@@ -97,7 +97,7 @@ static union intr_pipefds intr_pipe;
 static struct rte_intr_source_list intr_sources;
 
 /* interrupt handling thread */
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 /* VFIO interrupts */
 #ifdef VFIO_PRESENT
@@ -1570,5 +1570,5 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
 
 int rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
diff --git a/lib/eal/linux/eal_thread.c b/lib/eal/linux/eal_thread.c
index 83c2034b93..fe6b02788f 100644
--- a/lib/eal/linux/eal_thread.c
+++ b/lib/eal/linux/eal_thread.c
@@ -73,15 +73,15 @@ eal_thread_loop(__rte_unused void *arg)
 	char c;
 	int n, ret;
 	unsigned lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id,lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -93,8 +93,8 @@ eal_thread_loop(__rte_unused void *arg)
 	__rte_thread_init(lcore_id, &lcore_config[lcore_id].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 ? "" : "...");
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (cpuset=[%s%s])\n",
+		lcore_id, cpuset, ret == 0 ? "" : "...");
 
 	rte_eal_trace_thread_lcore_ready(lcore_id, cpuset);
 
@@ -148,7 +148,7 @@ int rte_sys_gettid(void)
 	return (int)syscall(SYS_gettid);
 }
 
-int rte_thread_setname(pthread_t id, const char *name)
+int rte_thread_setname(rte_thread_t id, const char *name)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
@@ -156,7 +156,7 @@ int rte_thread_setname(pthread_t id, const char *name)
 	char truncated[16];
 
 	strlcpy(truncated, name, sizeof(truncated));
-	ret = pthread_setname_np(id, truncated);
+	ret = pthread_setname_np(id.opaque_id, truncated);
 #endif
 #endif
 	RTE_SET_USED(id);
@@ -164,12 +164,12 @@ int rte_thread_setname(pthread_t id, const char *name)
 	return -ret;
 }
 
-int rte_thread_getname(pthread_t id, char *name, size_t len)
+int rte_thread_getname(rte_thread_t id, char *name, size_t len)
 {
 	int ret = ENOSYS;
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
 #if __GLIBC_PREREQ(2, 12)
-	ret = pthread_getname_np(id, name, len);
+	ret = pthread_getname_np(id.opaque_id, name, len);
 #endif
 #endif
 	RTE_SET_USED(id);
diff --git a/lib/eal/linux/eal_timer.c b/lib/eal/linux/eal_timer.c
index 7cf15cabac..b4099a0aa2 100644
--- a/lib/eal/linux/eal_timer.c
+++ b/lib/eal/linux/eal_timer.c
@@ -80,7 +80,7 @@ static uint64_t eal_hpet_resolution_hz = 0;
 /* Incremented 4 times during one 32bits hpet full count */
 static uint32_t eal_hpet_msb;
 
-static pthread_t msb_inc_thread_id;
+static rte_thread_t msb_inc_thread_id;
 
 /*
  * This function runs on a specific thread to update a global variable
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index dc711b4240..f2b8063760 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
         'eal_file.c',
         'eal_unix_memory.c',
         'eal_unix_timer.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c
deleted file mode 100644
index c72d619ec1..0000000000
--- a/lib/eal/unix/rte_thread.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2021 Mellanox Technologies, Ltd
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_log.h>
-#include <rte_thread.h>
-
-struct eal_tls_key {
-	pthread_key_t thread_index;
-};
-
-int
-rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
-{
-	int err;
-
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
-		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
-	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
-			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-int
-rte_thread_key_delete(rte_thread_key key)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_key_delete(key->thread_index);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
-			 strerror(err));
-		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	free(key);
-	return 0;
-}
-
-int
-rte_thread_value_set(rte_thread_key key, const void *value)
-{
-	int err;
-
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
-		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
-			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
-	}
-	return 0;
-}
-
-void *
-rte_thread_value_get(rte_thread_key key)
-{
-	if (!key) {
-		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return NULL;
-	}
-	return pthread_getspecific(key->thread_index);
-}
diff --git a/lib/eal/version.map b/lib/eal/version.map
index fe5c3dac98..3126c77e4d 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,28 @@ EXPERIMENTAL {
 	rte_version_release; # WINDOWS_NO_EXPORT
 	rte_version_suffix; # WINDOWS_NO_EXPORT
 	rte_version_year; # WINDOWS_NO_EXPORT
+
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_init;
+	rte_thread_mutex_destroy;
+	rte_thread_create;
+	rte_thread_set_affinity_by_id;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_priority;
+	rte_thread_attr_init;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_get_affinity;
+	rte_thread_join;
+	rte_thread_self;
+	rte_thread_equal;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
+	rte_thread_cancel; # WINDOWS_NO_EXPORT
+	rte_thread_detach;
+	rte_thread_attr_set_priority;
+
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c
index 28c787c0b0..3e0834a24a 100644
--- a/lib/eal/windows/eal.c
+++ b/lib/eal/windows/eal.c
@@ -274,6 +274,8 @@ rte_eal_init(int argc, char **argv)
 		eal_get_internal_configuration();
 	int ret;
 
+	rte_thread_priority_init();
+
 	eal_log_init(NULL, 0);
 
 	eal_log_level_parse(argc, argv);
@@ -375,6 +377,36 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	if (rte_thread_set_affinity_by_id(rte_thread_self(),
+			&lcore_config[config->main_lcore].cpuset) != 0) {
+		rte_eal_init_alert("Cannot set affinity");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	ret = rte_thread_set_priority(rte_thread_self(),
+				      internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority");
+		rte_errno = ret;
+		return -1;
+	}
+
+	rte_thread_attr_t thread_attr;
+	ret = rte_thread_attr_init(&thread_attr);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot initialize thread attributes");
+		rte_errno = ret;
+		return -1;
+	}
+	ret = rte_thread_attr_set_priority(&thread_attr,
+					   internal_conf->thread_priority);
+	if (ret != 0) {
+		rte_eal_init_alert("Cannot set thread priority attribute");
+		rte_errno = ret;
+		return -1;
+	}
+
 	RTE_LCORE_FOREACH_WORKER(i) {
 
 		/*
@@ -390,8 +422,17 @@ rte_eal_init(int argc, char **argv)
 
 		lcore_config[i].state = WAIT;
 
+		ret = rte_thread_attr_set_affinity(&thread_attr, &lcore_config[i].cpuset);
+		if (ret != 0) {
+			rte_eal_init_alert("Cannot set thread affinity attribute");
+			rte_errno = ret;
+			return -1;
+		}
+
 		/* create a thread for each lcore */
-		if (eal_thread_create(&lcore_config[i].thread_id) != 0)
+		ret = rte_thread_create(&lcore_config[i].thread_id,
+					&thread_attr, eal_thread_loop, NULL);
+		if (ret != 0)
 			rte_panic("Cannot create thread\n");
 	}
 
diff --git a/lib/eal/windows/eal_interrupts.c b/lib/eal/windows/eal_interrupts.c
index 1d4cf794df..a529ef95e3 100644
--- a/lib/eal/windows/eal_interrupts.c
+++ b/lib/eal/windows/eal_interrupts.c
@@ -2,12 +2,14 @@
  * Copyright 2020 Mellanox Technologies, Ltd
  */
 
+#include <inttypes.h>
+
 #include <rte_interrupts.h>
 
 #include "eal_private.h"
 #include "eal_windows.h"
 
-static pthread_t intr_thread;
+static rte_thread_t intr_thread;
 
 static HANDLE intr_iocp;
 
@@ -76,7 +78,7 @@ rte_eal_intr_init(void)
 int
 rte_thread_is_intr(void)
 {
-	return pthread_equal(intr_thread, pthread_self());
+	return rte_thread_equal(intr_thread, rte_thread_self());
 }
 
 int
@@ -92,9 +94,9 @@ eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
 {
 	HANDLE handle;
 
-	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
+	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread.opaque_id);
 	if (handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		RTE_LOG_WIN32_ERR("OpenThread (%" PRIuPTR ")", intr_thread.opaque_id);
 		return -ENOENT;
 	}
 
diff --git a/lib/eal/windows/eal_thread.c b/lib/eal/windows/eal_thread.c
index 9c3f6d69fd..0c6bca24cf 100644
--- a/lib/eal/windows/eal_thread.c
+++ b/lib/eal/windows/eal_thread.c
@@ -60,15 +60,15 @@ eal_thread_loop(void *arg __rte_unused)
 	char c;
 	int n, ret;
 	unsigned int lcore_id;
-	pthread_t thread_id;
+	rte_thread_t thread_id;
 	int m2w, w2m;
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 
-	thread_id = pthread_self();
+	thread_id = rte_thread_self();
 
 	/* retrieve our lcore_id from the configuration structure */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
-		if (thread_id == lcore_config[lcore_id].thread_id)
+		if (rte_thread_equal(thread_id, lcore_config[lcore_id].thread_id))
 			break;
 	}
 	if (lcore_id == RTE_MAX_LCORE)
@@ -80,7 +80,7 @@ eal_thread_loop(void *arg __rte_unused)
 	__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);
+		lcore_id, thread_id.opaque_id, cpuset);
 
 	/* read on our pipe to get commands */
 	while (1) {
@@ -122,24 +122,6 @@ eal_thread_loop(void *arg __rte_unused)
 	}
 }
 
-/* function to create threads */
-int
-eal_thread_create(pthread_t *thread)
-{
-	HANDLE th;
-
-	th = CreateThread(NULL, 0,
-		(LPTHREAD_START_ROUTINE)(ULONG_PTR)eal_thread_loop,
-						NULL, 0, (LPDWORD)thread);
-	if (!th)
-		return -1;
-
-	SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-	SetThreadPriority(th, THREAD_PRIORITY_NORMAL);
-
-	return 0;
-}
-
 /* get current thread ID */
 int
 rte_sys_gettid(void)
@@ -148,7 +130,7 @@ rte_sys_gettid(void)
 }
 
 int
-rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name)
+rte_thread_setname(__rte_unused rte_thread_t id, __rte_unused const char *name)
 {
 	/* TODO */
 	/* This is a stub, not the expected result */
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index dc5dc8240a..4b92b198c7 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -35,16 +35,6 @@
  */
 int eal_create_cpu_map(void);
 
-/**
- * Create a thread.
- *
- * @param thread
- *   The location to store the thread id if successful.
- * @return
- *   0 for success, -1 if the thread is not created.
- */
-int eal_thread_create(pthread_t *thread);
-
 /**
  * Get system NUMA node number for a socket ID.
  *
diff --git a/lib/eal/windows/include/meson.build b/lib/eal/windows/include/meson.build
index b3534b025f..7d9b3393e4 100644
--- a/lib/eal/windows/include/meson.build
+++ b/lib/eal/windows/include/meson.build
@@ -7,4 +7,5 @@ headers += files(
         'rte_os.h',
         'rte_virt2phys.h',
         'rte_windows.h',
+        'rte_windows_thread_types.h',
 )
diff --git a/lib/eal/windows/include/pthread.h b/lib/eal/windows/include/pthread.h
deleted file mode 100644
index 27fd2cca52..0000000000
--- a/lib/eal/windows/include/pthread.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019 Intel Corporation
- */
-
-#ifndef _PTHREAD_H_
-#define _PTHREAD_H_
-
-#include <stdint.h>
-#include <sched.h>
-
-/**
- * This file is required to support the common code in eal_common_proc.c,
- * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
- * does not contain pthread.h. This may be removed in future releases.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_common.h>
-#include <rte_windows.h>
-
-#define PTHREAD_BARRIER_SERIAL_THREAD TRUE
-
-/* defining pthread_t type on Windows since there is no in Microsoft libc*/
-typedef uintptr_t pthread_t;
-
-/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
-typedef void *pthread_attr_t;
-
-typedef void *pthread_mutexattr_t;
-
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
-
-#define pthread_barrier_init(barrier, attr, count) \
-	!InitializeSynchronizationBarrier(barrier, count, -1)
-#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
-	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
-#define pthread_barrier_destroy(barrier) \
-	!DeleteSynchronizationBarrier(barrier)
-#define pthread_cancel(thread) !TerminateThread((HANDLE) thread, 0)
-
-/* pthread function overrides */
-#define pthread_self() \
-	((pthread_t)GetCurrentThreadId())
-
-
-static inline int
-pthread_equal(pthread_t t1, pthread_t t2)
-{
-	return t1 == t2;
-}
-
-static inline int
-pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	DWORD_PTR ret = 0;
-	HANDLE thread_handle;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("CloseHandle()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
-			rte_cpuset_t *cpuset)
-{
-	/* Workaround for the lack of a GetThreadAffinityMask()
-	 *API in Windows
-	 */
-	DWORD_PTR prev_affinity_mask;
-	HANDLE thread_handle;
-	DWORD_PTR ret = 0;
-
-	if (cpuset == NULL || cpuset_size == 0)
-		return -1;
-
-	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
-	if (thread_handle == NULL) {
-		RTE_LOG_WIN32_ERR("OpenThread()");
-		return -1;
-	}
-
-	/* obtain previous mask by setting dummy mask */
-	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
-	if (prev_affinity_mask == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	/* set it back! */
-	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
-	if (ret == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		goto close_handle;
-	}
-
-	memset(cpuset, 0, cpuset_size);
-	*cpuset->_bits = prev_affinity_mask;
-
-close_handle:
-	if (CloseHandle(thread_handle) == 0) {
-		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
-		return -1;
-	}
-	return (ret == 0) ? -1 : 0;
-}
-
-static inline int
-pthread_create(void *threadid, const void *threadattr, void *threadfunc,
-		void *args)
-{
-	RTE_SET_USED(threadattr);
-	HANDLE hThread;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
-		args, 0, (LPDWORD)threadid);
-	if (hThread) {
-		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-	}
-	return ((hThread != NULL) ? 0 : E_FAIL);
-}
-
-static inline int
-pthread_detach(__rte_unused pthread_t thread)
-{
-	return 0;
-}
-
-static inline int
-pthread_join(__rte_unused pthread_t thread,
-	__rte_unused void **value_ptr)
-{
-	return 0;
-}
-
-static inline int
-pthread_mutex_init(pthread_mutex_t *mutex,
-		   __rte_unused pthread_mutexattr_t *attr)
-{
-	InitializeCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	EnterCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	LeaveCriticalSection(mutex);
-	return 0;
-}
-
-static inline int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-	DeleteCriticalSection(mutex);
-	return 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PTHREAD_H_ */
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/meson.build b/lib/eal/windows/meson.build
index ff9cbec417..4b7db4754b 100644
--- a/lib/eal/windows/meson.build
+++ b/lib/eal/windows/meson.build
@@ -19,7 +19,12 @@ sources += files(
         'eal_timer.c',
         'fnmatch.c',
         'getopt.c',
-        'rte_thread.c',
 )
 
+if get_option('use_external_thread_lib')
+	sources += 'eal/common/rte_thread.c'
+else
+	sources += 'eal/windows/rte_thread.c'
+endif
+
 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true)
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index c607eabb5b..bc0a4c973a 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -526,7 +526,7 @@ rte_eth_dev_allocate(const char *name)
 	strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = RTE_ETHER_MTU;
-	pthread_mutex_init(&eth_dev->data->flow_ops_mutex, NULL);
+	rte_thread_mutex_init(&eth_dev->data->flow_ops_mutex);
 
 unlock:
 	rte_spinlock_unlock(&eth_dev_shared_data->ownership_lock);
@@ -600,7 +600,7 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 		rte_free(eth_dev->data->mac_addrs);
 		rte_free(eth_dev->data->hash_mac_addrs);
 		rte_free(eth_dev->data->dev_private);
-		pthread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
+		rte_thread_mutex_destroy(&eth_dev->data->flow_ops_mutex);
 		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
 	}
 
diff --git a/lib/ethdev/rte_ethdev_core.h b/lib/ethdev/rte_ethdev_core.h
index 4679d948fa..ad1053b561 100644
--- a/lib/ethdev/rte_ethdev_core.h
+++ b/lib/ethdev/rte_ethdev_core.h
@@ -5,7 +5,8 @@
 #ifndef _RTE_ETHDEV_CORE_H_
 #define _RTE_ETHDEV_CORE_H_
 
-#include <pthread.h>
+#include <rte_thread.h>
+#include <sys/types.h>
 
 /**
  * @file
@@ -182,7 +183,7 @@ struct rte_eth_dev_data {
 			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
 			 */
 
-	pthread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
+	rte_thread_mutex_t flow_ops_mutex; /**< rte_flow ops mutex. */
 	uint64_t reserved_64s[4]; /**< Reserved for future fields */
 	void *reserved_ptrs[4];   /**< Reserved for future fields */
 } __rte_cache_aligned;
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 8cb7a069c8..4f112d1af7 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -226,14 +226,14 @@ static inline void
 fts_enter(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_lock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_lock(&dev->data->flow_ops_mutex);
 }
 
 static inline void
 fts_exit(struct rte_eth_dev *dev)
 {
 	if (!(dev->data->dev_flags & RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE))
-		pthread_mutex_unlock(&dev->data->flow_ops_mutex);
+		rte_thread_mutex_unlock(&dev->data->flow_ops_mutex);
 }
 
 static int
diff --git a/lib/eventdev/rte_event_eth_rx_adapter.c b/lib/eventdev/rte_event_eth_rx_adapter.c
index 13dfb28401..be39cf9089 100644
--- a/lib/eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/eventdev/rte_event_eth_rx_adapter.c
@@ -147,7 +147,7 @@ struct rte_event_eth_rx_adapter {
 	/* Count of interrupt vectors in use */
 	uint32_t num_intr_vec;
 	/* Thread blocked on Rx interrupts */
-	pthread_t rx_intr_thread;
+	rte_thread_t rx_intr_thread;
 	/* Configuration callback for rte_service configuration */
 	rte_event_eth_rx_adapter_conf_cb conf_cb;
 	/* Configuration callback argument */
@@ -1449,12 +1449,12 @@ rxa_destroy_intr_thread(struct rte_event_eth_rx_adapter *rx_adapter)
 {
 	int err;
 
-	err = pthread_cancel(rx_adapter->rx_intr_thread);
+	err = rte_thread_cancel(rx_adapter->rx_intr_thread);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't cancel interrupt thread err = %d\n",
 				err);
 
-	err = pthread_join(rx_adapter->rx_intr_thread, NULL);
+	err = rte_thread_join(rx_adapter->rx_intr_thread, NULL);
 	if (err)
 		RTE_EDEV_LOG_ERR("Can't join interrupt thread err = %d\n", err);
 
diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c
index 55d4856f9e..b97774ccd4 100644
--- a/lib/vhost/fd_man.c
+++ b/lib/vhost/fd_man.c
@@ -61,9 +61,9 @@ fdset_shrink_nolock(struct fdset *pfdset)
 static void
 fdset_shrink(struct fdset *pfdset)
 {
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	fdset_shrink_nolock(pfdset);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 }
 
 /**
@@ -126,21 +126,21 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat)
 	if (pfdset == NULL || fd == -1)
 		return -1;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 	if (i == -1) {
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		fdset_shrink_nolock(pfdset);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		i = pfdset->num < MAX_FDS ? pfdset->num++ : -1;
 		if (i == -1) {
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 			return -2;
 		}
 	}
 
 	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 	return 0;
 }
@@ -159,7 +159,7 @@ fdset_del(struct fdset *pfdset, int fd)
 		return NULL;
 
 	do {
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 		i = fdset_find_fd(pfdset, fd);
 		if (i != -1 && pfdset->fd[i].busy == 0) {
@@ -170,7 +170,7 @@ fdset_del(struct fdset *pfdset, int fd)
 			pfdset->fd[i].dat = NULL;
 			i = -1;
 		}
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	} while (i != -1);
 
 	return dat;
@@ -192,10 +192,10 @@ fdset_try_del(struct fdset *pfdset, int fd)
 	if (pfdset == NULL || fd == -1)
 		return -2;
 
-	pthread_mutex_lock(&pfdset->fd_mutex);
+	rte_thread_mutex_lock(&pfdset->fd_mutex);
 	i = fdset_find_fd(pfdset, fd);
 	if (i != -1 && pfdset->fd[i].busy) {
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 		return -1;
 	}
 
@@ -205,7 +205,7 @@ fdset_try_del(struct fdset *pfdset, int fd)
 		pfdset->fd[i].dat = NULL;
 	}
 
-	pthread_mutex_unlock(&pfdset->fd_mutex);
+	rte_thread_mutex_unlock(&pfdset->fd_mutex);
 	return 0;
 }
 
@@ -244,19 +244,19 @@ fdset_event_dispatch(void *arg)
 		 * might have been updated. It is ok if there is unwanted call
 		 * for new listenfds.
 		 */
-		pthread_mutex_lock(&pfdset->fd_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_mutex);
 		numfds = pfdset->num;
-		pthread_mutex_unlock(&pfdset->fd_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
-		pthread_mutex_lock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_lock(&pfdset->fd_pooling_mutex);
 		val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */);
-		pthread_mutex_unlock(&pfdset->fd_pooling_mutex);
+		rte_thread_mutex_unlock(&pfdset->fd_pooling_mutex);
 		if (val < 0)
 			continue;
 
 		need_shrink = 0;
 		for (i = 0; i < numfds; i++) {
-			pthread_mutex_lock(&pfdset->fd_mutex);
+			rte_thread_mutex_lock(&pfdset->fd_mutex);
 
 			pfdentry = &pfdset->fd[i];
 			fd = pfdentry->fd;
@@ -264,12 +264,12 @@ fdset_event_dispatch(void *arg)
 
 			if (fd < 0) {
 				need_shrink = 1;
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
 			if (!pfd->revents) {
-				pthread_mutex_unlock(&pfdset->fd_mutex);
+				rte_thread_mutex_unlock(&pfdset->fd_mutex);
 				continue;
 			}
 
@@ -280,7 +280,7 @@ fdset_event_dispatch(void *arg)
 			dat = pfdentry->dat;
 			pfdentry->busy = 1;
 
-			pthread_mutex_unlock(&pfdset->fd_mutex);
+			rte_thread_mutex_unlock(&pfdset->fd_mutex);
 
 			if (rcb && pfd->revents & (POLLIN | FDPOLLERR))
 				rcb(fd, dat, &remove1);
diff --git a/lib/vhost/fd_man.h b/lib/vhost/fd_man.h
index 3ab5cfdd60..ba58d849e8 100644
--- a/lib/vhost/fd_man.h
+++ b/lib/vhost/fd_man.h
@@ -5,7 +5,7 @@
 #ifndef _FD_MAN_H_
 #define _FD_MAN_H_
 #include <stdint.h>
-#include <pthread.h>
+#include <rte_thread.h>
 #include <poll.h>
 
 #define MAX_FDS 1024
@@ -23,8 +23,8 @@ struct fdentry {
 struct fdset {
 	struct pollfd rwfds[MAX_FDS];
 	struct fdentry fd[MAX_FDS];
-	pthread_mutex_t fd_mutex;
-	pthread_mutex_t fd_pooling_mutex;
+	rte_thread_mutex_t fd_mutex;
+	rte_thread_mutex_t fd_pooling_mutex;
 	int num;	/* current fd number of this fdset */
 
 	union pipefds {
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
index 5d0d728d52..36a430ae25 100644
--- a/lib/vhost/socket.c
+++ b/lib/vhost/socket.c
@@ -14,7 +14,7 @@
 #include <sys/queue.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <pthread.h>
+#include <rte_thread.h>
 
 #include <rte_log.h>
 
@@ -31,7 +31,7 @@ TAILQ_HEAD(vhost_user_connection_list, vhost_user_connection);
  */
 struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
-	pthread_mutex_t conn_mutex;
+	rte_thread_mutex_t conn_mutex;
 	char *path;
 	int socket_fd;
 	struct sockaddr_un un;
@@ -74,7 +74,7 @@ struct vhost_user {
 	struct vhost_user_socket *vsockets[MAX_VHOST_SOCKET];
 	struct fdset fdset;
 	int vsocket_cnt;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 #define MAX_VIRTIO_BACKLOG 128
@@ -87,12 +87,12 @@ static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 static struct vhost_user vhost_user = {
 	.fdset = {
 		.fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} },
-		.fd_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.fd_pooling_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.fd_mutex = RTE_THREAD_MUTEX_INITIALIZER,
+		.fd_pooling_mutex = RTE_THREAD_MUTEX_INITIALIZER,
 		.num = 0
 	},
 	.vsocket_cnt = 0,
-	.mutex = PTHREAD_MUTEX_INITIALIZER,
+	.mutex = RTE_THREAD_MUTEX_INITIALIZER,
 };
 
 /*
@@ -271,9 +271,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 		goto err_cleanup;
 	}
 
-	pthread_mutex_lock(&vsocket->conn_mutex);
+	rte_thread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
-	pthread_mutex_unlock(&vsocket->conn_mutex);
+	rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 	fdset_pipe_notify(&vhost_user.fdset);
 	return;
@@ -326,9 +326,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 			vhost_user_start_client(vsocket);
 		}
 
-		pthread_mutex_lock(&vsocket->conn_mutex);
+		rte_thread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
-		pthread_mutex_unlock(&vsocket->conn_mutex);
+		rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
 	}
@@ -420,11 +420,11 @@ struct vhost_user_reconnect {
 TAILQ_HEAD(vhost_user_reconnect_tailq_list, vhost_user_reconnect);
 struct vhost_user_reconnect_list {
 	struct vhost_user_reconnect_tailq_list head;
-	pthread_mutex_t mutex;
+	rte_thread_mutex_t mutex;
 };
 
 static struct vhost_user_reconnect_list reconn_list;
-static pthread_t reconn_tid;
+static rte_thread_t reconn_tid;
 
 static int
 vhost_user_connect_nonblock(int fd, struct sockaddr *un, size_t sz)
@@ -456,7 +456,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 	struct vhost_user_reconnect *reconn, *next;
 
 	while (1) {
-		pthread_mutex_lock(&reconn_list.mutex);
+		rte_thread_mutex_lock(&reconn_list.mutex);
 
 		/*
 		 * An equal implementation of TAILQ_FOREACH_SAFE,
@@ -487,7 +487,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
 			free(reconn);
 		}
 
-		pthread_mutex_unlock(&reconn_list.mutex);
+		rte_thread_mutex_unlock(&reconn_list.mutex);
 		sleep(1);
 	}
 
@@ -499,7 +499,7 @@ vhost_user_reconnect_init(void)
 {
 	int ret;
 
-	ret = pthread_mutex_init(&reconn_list.mutex, NULL);
+	ret = rte_thread_mutex_init(&reconn_list.mutex);
 	if (ret < 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
 		return ret;
@@ -510,7 +510,7 @@ vhost_user_reconnect_init(void)
 			     vhost_user_client_reconnect, NULL);
 	if (ret != 0) {
 		VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
-		if (pthread_mutex_destroy(&reconn_list.mutex)) {
+		if (rte_thread_mutex_destroy(&reconn_list.mutex)) {
 			VHOST_LOG_CONFIG(ERR,
 				"failed to destroy reconnect mutex");
 		}
@@ -554,9 +554,9 @@ vhost_user_start_client(struct vhost_user_socket *vsocket)
 	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 	TAILQ_INSERT_TAIL(&reconn_list.head, reconn, next);
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 
 	return 0;
 }
@@ -588,11 +588,11 @@ rte_vhost_driver_attach_vdpa_device(const char *path,
 	if (dev == NULL || path == NULL)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -602,11 +602,11 @@ rte_vhost_driver_detach_vdpa_device(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->vdpa_dev = NULL;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -617,11 +617,11 @@ rte_vhost_driver_get_vdpa_device(const char *path)
 	struct vhost_user_socket *vsocket;
 	struct rte_vdpa_device *dev = NULL;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		dev = vsocket->vdpa_dev;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return dev;
 }
@@ -631,7 +631,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 
 	/* Note that use_builtin_virtio_net is not affected by this function
@@ -641,7 +641,7 @@ rte_vhost_driver_disable_features(const char *path, uint64_t features)
 
 	if (vsocket)
 		vsocket->features &= ~features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -651,7 +651,7 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		if ((vsocket->supported_features & features) != features) {
@@ -659,12 +659,12 @@ rte_vhost_driver_enable_features(const char *path, uint64_t features)
 			 * trying to enable features the driver doesn't
 			 * support.
 			 */
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 			return -1;
 		}
 		vsocket->features |= features;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -674,7 +674,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
 		vsocket->supported_features = features;
@@ -685,7 +685,7 @@ rte_vhost_driver_set_features(const char *path, uint64_t features)
 		 */
 		vsocket->use_builtin_virtio_net = false;
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -698,7 +698,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -724,7 +724,7 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features)
 	*features = vsocket->features & vdpa_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -734,11 +734,11 @@ rte_vhost_driver_set_protocol_features(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->protocol_features = protocol_features;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return vsocket ? 0 : -1;
 }
 
@@ -751,7 +751,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -779,7 +779,7 @@ rte_vhost_driver_get_protocol_features(const char *path,
 		& vdpa_protocol_features;
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -791,7 +791,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	struct rte_vdpa_device *vdpa_dev;
 	int ret = 0;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (!vsocket) {
 		VHOST_LOG_CONFIG(ERR,
@@ -817,7 +817,7 @@ rte_vhost_driver_get_queue_num(const char *path, uint32_t *queue_num)
 	*queue_num = RTE_MIN((uint32_t)VHOST_MAX_QUEUE_PAIRS, vdpa_queue_num);
 
 unlock_exit:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 }
 
@@ -849,7 +849,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 	if (!path)
 		return -1;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
 		VHOST_LOG_CONFIG(ERR,
@@ -869,7 +869,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 		goto out;
 	}
 	TAILQ_INIT(&vsocket->conn_list);
-	ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
+	ret = rte_thread_mutex_init(&vsocket->conn_mutex);
 	if (ret) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to init connection mutex\n");
@@ -951,7 +951,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
-		if (vsocket->reconnect && reconn_tid == 0) {
+		if (vsocket->reconnect && reconn_tid.opaque_id == 0) {
 			if (vhost_user_reconnect_init() != 0)
 				goto out_mutex;
 		}
@@ -965,18 +965,18 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
 
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 	return ret;
 
 out_mutex:
-	if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
+	if (rte_thread_mutex_destroy(&vsocket->conn_mutex)) {
 		VHOST_LOG_CONFIG(ERR,
 			"error: failed to destroy connection mutex\n");
 	}
 out_free:
 	vhost_user_socket_mem_free(vsocket);
 out:
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return ret;
 }
@@ -987,7 +987,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 	int found = false;
 	struct vhost_user_reconnect *reconn, *next;
 
-	pthread_mutex_lock(&reconn_list.mutex);
+	rte_thread_mutex_lock(&reconn_list.mutex);
 
 	for (reconn = TAILQ_FIRST(&reconn_list.head);
 	     reconn != NULL; reconn = next) {
@@ -1001,7 +1001,7 @@ vhost_user_remove_reconnect(struct vhost_user_socket *vsocket)
 			break;
 		}
 	}
-	pthread_mutex_unlock(&reconn_list.mutex);
+	rte_thread_mutex_unlock(&reconn_list.mutex);
 	return found;
 }
 
@@ -1019,13 +1019,13 @@ rte_vhost_driver_unregister(const char *path)
 		return -1;
 
 again:
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 
 	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
-			pthread_mutex_lock(&vsocket->conn_mutex);
+			rte_thread_mutex_lock(&vsocket->conn_mutex);
 			for (conn = TAILQ_FIRST(&vsocket->conn_list);
 			     conn != NULL;
 			     conn = next) {
@@ -1039,9 +1039,10 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
-					pthread_mutex_unlock(
+					rte_thread_mutex_unlock(
 							&vsocket->conn_mutex);
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1053,7 +1054,7 @@ rte_vhost_driver_unregister(const char *path)
 				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 				free(conn);
 			}
-			pthread_mutex_unlock(&vsocket->conn_mutex);
+			rte_thread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
 				/*
@@ -1063,7 +1064,8 @@ rte_vhost_driver_unregister(const char *path)
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						vsocket->socket_fd) == -1) {
-					pthread_mutex_unlock(&vhost_user.mutex);
+					rte_thread_mutex_unlock(
+							&vhost_user.mutex);
 					goto again;
 				}
 
@@ -1073,18 +1075,18 @@ rte_vhost_driver_unregister(const char *path)
 				vhost_user_remove_reconnect(vsocket);
 			}
 
-			pthread_mutex_destroy(&vsocket->conn_mutex);
+			rte_thread_mutex_destroy(&vsocket->conn_mutex);
 			vhost_user_socket_mem_free(vsocket);
 
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;
-			pthread_mutex_unlock(&vhost_user.mutex);
+			rte_thread_mutex_unlock(&vhost_user.mutex);
 
 			return 0;
 		}
 	}
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return -1;
 }
@@ -1098,11 +1100,11 @@ rte_vhost_driver_callback_register(const char *path,
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket)
 		vsocket->notify_ops = ops;
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
 }
@@ -1112,9 +1114,9 @@ vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->notify_ops : NULL;
 }
@@ -1123,16 +1125,16 @@ int
 rte_vhost_driver_start(const char *path)
 {
 	struct vhost_user_socket *vsocket;
-	static pthread_t fdset_tid;
+	static rte_thread_t fdset_tid;
 
-	pthread_mutex_lock(&vhost_user.mutex);
+	rte_thread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	pthread_mutex_unlock(&vhost_user.mutex);
+	rte_thread_mutex_unlock(&vhost_user.mutex);
 
 	if (!vsocket)
 		return -1;
 
-	if (fdset_tid == 0) {
+	if (fdset_tid.opaque_id == 0) {
 		/**
 		 * create a pipe which will be waited by poll and notified to
 		 * rebuild the wait list of poll.
diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c
index c96f6335c8..ee7470bf8b 100644
--- a/lib/vhost/vhost.c
+++ b/lib/vhost/vhost.c
@@ -26,7 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
-pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
+rte_thread_mutex_t vhost_dev_lock = RTE_THREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -657,7 +657,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
-	pthread_mutex_lock(&vhost_dev_lock);
+	rte_thread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -666,7 +666,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to find a free slot for new device.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -674,12 +674,12 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		VHOST_LOG_CONFIG(ERR,
 			"Failed to allocate memory for new dev.\n");
-		pthread_mutex_unlock(&vhost_dev_lock);
+		rte_thread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
-	pthread_mutex_unlock(&vhost_dev_lock);
+	rte_thread_mutex_unlock(&vhost_dev_lock);
 
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
diff --git a/meson_options.txt b/meson_options.txt
index 56bdfd0f0a..46d156cf2f 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -42,5 +42,7 @@ option('enable_trace_fp', type: 'boolean', value: false, description:
        'enable fast path trace points.')
 option('tests', type: 'boolean', value: true, description:
        'build unit tests')
+option('use_external_thread_lib', type: 'boolean', value: false,
+	description: 'use an external thread library')
 option('use_hpet', type: 'boolean', value: false, description:
        'use HPET timer in EAL')
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-06-08  5:50                           ` Narcisa Ana Maria Vasile
  2021-06-08  7:45                             ` David Marchand
  2021-06-08 23:08                             ` Dmitry Kozlyuk
  0 siblings, 2 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-08  5:50 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

On Fri, Jun 04, 2021 at 04:44:34PM -0700, Narcisa Ana Maria Vasile wrote:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Rename pthread_* occurrences with the new rte_thread_* API.
> Enable the new API in the build system.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---

I'll send v10. 
Can someone please help with an example on how to check for ABI breaks? Thank you!

I've run:
DPDK_ABI_REF_VERSION=v21.05 DPDK_ABI_REF_DIR=~/ref ./devtools/test-meson-builds.sh
which doesn't give any warnings about the ABI break.

I've cloned the dpdk repo in "~/ref" and checkout v21.05 tag.
"~/dpdk" is on a local branch that contains my changes:

"./devtools/check-abi.sh ~/ref ~/dpdk" - didn't work.

I've then used gen-abi.sh (with a small change to skip the *.symbols,
since abidw can't handle them) to generate the *.dump files. Reruning check-abi.sh
worked this time, but didn't show the ABI break. This is the entire output:

------
WARNING: could not identify an include directory for /home/administrator/ref, expect false positives...
WARNING: could not identify an include directory for /home/administrator/dpdk, expect false positives...
Functions changes summary: 0 Removed, 0 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
------

I've also tried to compare each file:
abidiff --suppr ./devtools/libabigail.abignore --no-added-syms  ~/ref/dump/librte_eal.dump ~/dpdk/dump/librte_eal.dump


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API
  2021-06-08  5:50                           ` Narcisa Ana Maria Vasile
@ 2021-06-08  7:45                             ` David Marchand
  2021-06-18 21:53                               ` Narcisa Ana Maria Vasile
  2021-06-08 23:08                             ` Dmitry Kozlyuk
  1 sibling, 1 reply; 290+ messages in thread
From: David Marchand @ 2021-06-08  7:45 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, Thomas Monjalon, Dmitry Kozlyuk, Khoa To, navasile,
	Dmitry Malloy (MESHCHANINOV),
	roretzla, Tal Shnaiderman, Omar Cardona, Bruce Richardson,
	Pallavi Kadam

On Tue, Jun 8, 2021 at 7:50 AM Narcisa Ana Maria Vasile
<navasile@linux.microsoft.com> wrote:
>
> On Fri, Jun 04, 2021 at 04:44:34PM -0700, Narcisa Ana Maria Vasile wrote:
> > From: Narcisa Vasile <navasile@microsoft.com>
> >
> > Rename pthread_* occurrences with the new rte_thread_* API.
> > Enable the new API in the build system.
> >
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
>
> I'll send v10.
> Can someone please help with an example on how to check for ABI breaks? Thank you!
>
> I've run:
> DPDK_ABI_REF_VERSION=v21.05 DPDK_ABI_REF_DIR=~/ref ./devtools/test-meson-builds.sh
> which doesn't give any warnings about the ABI break.

This should work the way you tried if you have working toolchains and
libabigail installed.
Something is off in your env.

Side note: ovsrobot is out those days (we have some trouble in one of
RH labs and it happens ovsrobot is hosted there), but you could try
with a github repo of yours + GHA, and the ABI failure should be
caught too.


I just tried on my rhel7 (gcc 4.8.5 + libabigail 1.8.2) with your
series applied.
$ DPDK_ABI_REF_VERSION=v21.05
DPDK_ABI_REF_DIR=~/git/pub/dpdk.org/reference
./devtools/test-meson-builds.sh
...
Error: ABI issue reported for 'abidiff --suppr
/home/dmarchan/git/pub/dpdk.org/devtools/../devtools/libabigail.abignore
--no-added-syms --headers-dir1
/home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/usr/local/include
--headers-dir2 /home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/usr/local/include
/home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/dump/librte_eal.dump
/home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/dump/librte_eal.dump'
ABIDIFF_ABI_CHANGE, this change requires a review (abidiff flagged
this as a potential issue).


$ abidiff --suppr
/home/dmarchan/git/pub/dpdk.org/devtools/../devtools/libabigail.abignore
--no-added-syms --headers-dir1
/home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/usr/local/include
--headers-dir2 /home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/usr/local/include
/home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/dump/librte_eal.dump
/home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/dump/librte_eal.dump
Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0
Added (20 filtered out) functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

2 functions with some indirect sub-type change:

  [C] 'function int rte_ctrl_thread_create(pthread_t*, const char*,
const pthread_attr_t*, void* (void*)*, void*)' at rte_lcore.h:443:1
has some indirect sub-type changes:
    parameter 1 of type 'pthread_t*' changed:
      in pointed to type 'typedef pthread_t' at rte_thread.h:42:1:
        typedef name changed from pthread_t to rte_thread_t at rte_thread.h:42:1
        underlying type 'unsigned long int' changed:
          entity changed from 'unsigned long int' to 'struct
rte_thread_tag' at rte_thread.h:40:1
          type size hasn't changed
    parameter 3 of type 'const pthread_attr_t*' changed:
      in pointed to type 'const pthread_attr_t':
        'const pthread_attr_t' changed to 'const rte_thread_attr_t'

  [C] 'function int rte_thread_setname(pthread_t, const char*)' at
rte_lcore.h:377:1 has some indirect sub-type changes:
    parameter 1 of type 'typedef pthread_t' changed:
      typedef name changed from pthread_t to rte_thread_t at rte_thread.h:42:1
      underlying type 'unsigned long int' changed:
        entity changed from 'unsigned long int' to 'struct
rte_thread_tag' at rte_thread.h:40:1
        type size hasn't changed



Can you check that in your env build-gcc-shared/ and the build
directory for references are configured with debug symbols?
You should see:
$ meson configure build-gcc-shared | awk '$1=="buildtype" {print $2}'
debugoptimized
$ meson configure reference/v21.05/build | awk '$1=="buildtype" {print $2}'
debugoptimized




>
> I've cloned the dpdk repo in "~/ref" and checkout v21.05 tag.
> "~/dpdk" is on a local branch that contains my changes:
>
> "./devtools/check-abi.sh ~/ref ~/dpdk" - didn't work.
>
> I've then used gen-abi.sh (with a small change to skip the *.symbols,
> since abidw can't handle them) to generate the *.dump files. Reruning check-abi.sh

gen-abi.sh is an internal script that works for an installed dpdk, not
a build directory.
$ ./devtools/gen-abi.sh
Usage: ./devtools/gen-abi.sh installdir


> worked this time, but didn't show the ABI break. This is the entire output:
>
> ------
> WARNING: could not identify an include directory for /home/administrator/ref, expect false positives...
> WARNING: could not identify an include directory for /home/administrator/dpdk, expect false positives...

check-abi.sh tries to find an include/ directory to filter changes on
private structures.
But there are multiple include/ dirs in a build directory, so the
script gives up on trying to filter and logs a warning.
This is not clearly written but, like gen-abi.sh, check-abi.sh works
on an installed directory.


> Functions changes summary: 0 Removed, 0 Changed, 0 Added function
> Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
> Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
> ------
>
> I've also tried to compare each file:
> abidiff --suppr ./devtools/libabigail.abignore --no-added-syms  ~/ref/dump/librte_eal.dump ~/dpdk/dump/librte_eal.dump
>

Without debug info, libabigail won't catch/report much but symbol
removals, or basic changes in function signatures.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
@ 2021-06-08 23:03                           ` Dmitry Kozlyuk
  2021-06-18 21:30                             ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:03 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Use a portable, type-safe representation for the thread identifier.
> Add functions for comparing thread ids and obtaining the thread id
> for the current thread.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/eal/common/rte_thread.c                   | 105 ++++++++++++++++++
>  lib/eal/include/rte_thread.h                  |  53 +++++++--
>  lib/eal/include/rte_thread_types.h            |  10 ++
>  .../include/rte_windows_thread_types.h        |  10 ++
>  lib/eal/windows/rte_thread.c                  |  17 +++
>  5 files changed, 186 insertions(+), 9 deletions(-)
>  create mode 100644 lib/eal/common/rte_thread.c
>  create mode 100644 lib/eal/include/rte_thread_types.h
>  create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h

It is strange that new files are being filled in the series, but are neither
compiled nor installed until the last patch. Any reason not to replace
lib/eal/unix/rte_thread.c starting from this patch?

A better name for rte_thread_types.h would be rte_posix_thread_types.h
to indicate this file is not really common.

> 
> diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
> new file mode 100644
> index 0000000000..1292f7a8f8
> --- /dev/null
> +++ b/lib/eal/common/rte_thread.c
> @@ -0,0 +1,105 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright 2021 Mellanox Technologies, Ltd
> + * Copyright(c) 2021 Microsoft Corporation
> + */
> +
> +#include <errno.h>
> +#include <pthread.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <rte_common.h>
> +#include <rte_errno.h>
> +#include <rte_log.h>
> +#include <rte_thread.h>
> +
> +struct eal_tls_key {
> +	pthread_key_t thread_index;
> +};
> +
> +rte_thread_t
> +rte_thread_self(void)
> +{
> +	rte_thread_t thread_id = { 0 };

(Applies to entire series.)
Please do not initialize variables when you intend to overwrite them.
This prevents compiler from reporting code paths where the variable is used
before a proper assignment.

> +
> +	thread_id.opaque_id = pthread_self();
> +
> +	return thread_id;
> +}
> +

[...]
> diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
> index 8be8ed8f36..347df1a6ae 100644
> --- a/lib/eal/include/rte_thread.h
> +++ b/lib/eal/include/rte_thread.h
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
>   * Copyright(c) 2021 Mellanox Technologies, Ltd
> + * Copyright(c) 2021 Microsoft Corporation
>   */
> +#include <stdint.h>
>  
>  #include <rte_os.h>
>  #include <rte_compat.h>
> @@ -20,11 +22,50 @@
>  extern "C" {
>  #endif
>  
> +#include <sched.h>
> +#if defined(RTE_USE_WINDOWS_THREAD_TYPES)

Redundant braces are discouraged in DPDK codebase.

[...]
> diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
> new file mode 100644
> index 0000000000..d67b24a563
> --- /dev/null
> +++ b/lib/eal/include/rte_thread_types.h
> @@ -0,0 +1,10 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Microsoft Corporation
> + */
> +
> +#ifndef _RTE_THREAD_TYPES_H_
> +#define _RTE_THREAD_TYPES_H_
> +
> +#include <pthread.h>
> +
> +#endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
> new file mode 100644
> index 0000000000..60e6d94553
> --- /dev/null
> +++ b/lib/eal/windows/include/rte_windows_thread_types.h
> @@ -0,0 +1,10 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Microsoft Corporation
> + */
> +
> +#ifndef _RTE_THREAD_TYPES_H_
> +#define _RTE_THREAD_TYPES_H_
> +
> +#include <rte_windows.h>
> +
> +#endif /* _RTE_THREAD_TYPES_H_ */

Thread types headers should have a check that forbids including them
directly, see lib/eal/$arch/rte_atomic_64.h for examples.

Note that rte_*_thread_types.h should be `indirect_headers`, not `headers`
in `meson.build` so that they're not checked by `buildtools/chkincs` when is
gets enabled for Windows. This is especially
true for lib/eal/common/rte_thread.h that cannot work without pthread.

However, in later patches these headers only contain mutex bits,
see the comment to pathc 07/10 about them. Maybe we don't need these files
after all.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 02/10] eal: add thread attributes
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-06-08 23:03                           ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:03 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Implement thread attributes for:
> * thread affinity
> * thread priority
> Implement functions for managing thread attributes.
> 
> Priority is represented through an enum that allows for two levels:
> 	- RTE_THREAD_PRIORITY_NORMAL
> 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
> 
> Affinity is described by the already known “rte_cpuset_t” type.

Is it my client or "rte_cpuset_t" is surrounded
by U+0093 (STS) and U+0094 (CCH)?

[...]
> diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
> index d67b24a563..996232c636 100644
> --- a/lib/eal/include/rte_thread_types.h
> +++ b/lib/eal/include/rte_thread_types.h
> @@ -7,4 +7,7 @@
>  
>  #include <pthread.h>
>  
> +#define EAL_THREAD_PRIORITY_NORMAL               0
> +#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL    99
> +
>  #endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
> index 60e6d94553..5bdeaad3d4 100644
> --- a/lib/eal/windows/include/rte_windows_thread_types.h
> +++ b/lib/eal/windows/include/rte_windows_thread_types.h
> @@ -7,4 +7,7 @@
>  
>  #include <rte_windows.h>
>  
> +#define EAL_THREAD_PRIORITY_NORMAL             THREAD_PRIORITY_NORMAL
> +#define EAL_THREAD_PRIORITY_REALTIME_CIRTICAL  THREAD_PRIORITY_TIME_CRITICAL
> +
>  #endif /* _RTE_THREAD_TYPES_H_ */

These constants are not used until patch 05/10 that removes them.
Am I missing something?
[...]


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-06-08 23:03                           ` Dmitry Kozlyuk
  2021-06-18 21:44                             ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:03 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
> index 6ea1dc2a05..9e74a538c2 100644
> --- a/lib/eal/windows/rte_thread.c
> +++ b/lib/eal/windows/rte_thread.c
> @@ -7,7 +7,8 @@
>  #include <rte_errno.h>
>  #include <rte_debug.h>
>  #include <rte_thread.h>
> -#include <rte_windows.h>
> +
> +#include "eal_windows.h"
>  
>  struct eal_tls_key {
>  	DWORD thread_index;
> @@ -77,6 +78,130 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
>  	return t1.opaque_id == t2.opaque_id;
>  }
>  
> +static int
> +rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
> +			       PGROUP_AFFINITY affinity)
> +{
> +	int ret = 0;
> +	PGROUP_AFFINITY cpu_affinity = NULL;
> +
> +	memset(affinity, 0, sizeof(GROUP_AFFINITY));
> +	affinity->Group = (USHORT)-1;
> +
> +	/* Check that all cpus of the set belong to the same processor group and
> +	 * accumulate thread affinity to be applied.
> +	 */
> +	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
> +		if (!CPU_ISSET(cpu_idx, cpuset))
> +			continue;
> +
> +		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
> +
> +		if (affinity->Group == (USHORT)-1) {
> +			affinity->Group = cpu_affinity->Group;
> +		} else if (affinity->Group != cpu_affinity->Group) {
> +			ret = EINVAL;
> +			goto cleanup;
> +		}
> +
> +		affinity->Mask |= cpu_affinity->Mask;
> +	}
> +
> +	if (affinity->Mask == 0) {
> +		ret = EINVAL;
> +		goto cleanup;
> +	}
> +
> +cleanup:
> +	return ret;
> +}

For v5 I asked a question that possibly got lost among other comments.
Repeating the question for convenience:

	Just to be clear: is it a kernel limitation that a thread can only
	run on cores of one processor group, or do we impose it so that API
	is atomic (transactional), i.e. because one of multiple
	SetThreadGroupAffinity() calls may fail and leave thread partially
	affinitized?

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v8 04/10] eal: implement functions for thread affinity management
  2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-06-08 23:04                         ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:04 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:38 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> +static int
> +rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
> +			       PGROUP_AFFINITY affinity)
> +{
> +	int ret = 0;
> +	PGROUP_AFFINITY cpu_affinity = NULL;
> +
> +	memset(affinity, 0, sizeof(GROUP_AFFINITY));
> +	affinity->Group = (USHORT)-1;
> +
> +	/* Check that all cpus of the set belong to the same processor group and
> +	 * accumulate thread affinity to be applied.
> +	 */
> +	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
> +		if (!CPU_ISSET(cpu_idx, cpuset))
> +			continue;
> +
> +		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
> +
> +		if (affinity->Group == (USHORT)-1) {
> +			affinity->Group = cpu_affinity->Group;
> +		} else if (affinity->Group != cpu_affinity->Group) {
> +			ret = EINVAL;
> +			goto cleanup;
> +		}
> +
> +		affinity->Mask |= cpu_affinity->Mask;
> +	}

For v5 I asked a question that possibly got lost among other comments.
Repeating it here for convenience:

	Just to be clear: is it a kernel limitation that a thread can only
	run on cores of one processor group, or do we impose it so that API
	is atomic (transactional), i.e. because one of multiple
	SetThreadGroupAffinity() calls may fail and leave thread partially
	affinitized?

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 05/10] eal: implement thread priority management functions
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-06-08 23:04                           ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:04 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
[...]
> diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
> index 9e74a538c2..6dc3d575c0 100644
> --- a/lib/eal/windows/rte_thread.c
> +++ b/lib/eal/windows/rte_thread.c
> @@ -202,6 +202,98 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
>  	return ret;
>  }
>  
> +static HANDLE
> +get_process_handle_from_thread_handle(HANDLE thread_handle)
> +{
> +	DWORD process_id = 0;
> +
> +	process_id = GetProcessIdOfThread(thread_handle);
> +	if (process_id == 0) {
> +		RTE_LOG_WIN32_ERR("GetProcessIdOfThread()");
> +		return NULL;
> +	}
> +
> +	return OpenProcess(PROCESS_SET_INFORMATION, FALSE, process_id);
> +}
> +

It is assumed all DPDK threads are created in current process,
existing code uses GetCurrentProcess(), so this can be dropped.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-06-08 23:04                           ` Dmitry Kozlyuk
  2021-06-18 21:41                             ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:04 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
> index 5c54cd9d67..1d481b9ad5 100644
> --- a/lib/eal/include/rte_thread.h
> +++ b/lib/eal/include/rte_thread.h
> @@ -208,6 +208,73 @@ __rte_experimental
>  int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
>  		enum rte_thread_priority priority);
>  
> +/**
> + * Create a new thread that will invoke the 'thread_func' routine.
> + *
> + * @param thread_id
> + *    A pointer that will store the id of the newly created thread.
> + *
> + * @param thread_attr
> + *    Attributes that are used at the creation of the new thread.
> + *
> + * @param thread_func
> + *    The routine that the new thread will invoke when starting execution.
> + *
> + * @param args
> + *    Arguments to be passed to the 'thread_func' routine.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.
> + */
> +__rte_experimental
> +int rte_thread_create(rte_thread_t *thread_id,
> +		      const rte_thread_attr_t *thread_attr,
> +		      void *(*thread_func)(void *), void *args);

1. Thread function prototype is used at least in 4 places,
maybe give it a name, like `rte_thread_func`?

2. We can't easily support it's `void*` return type on Windows,
because it doesn't fit in DWORD. In `rte_thread_join` below you use `int`.
All `pthread_join` usages in DPDK ignore return value, but I'd rather keep it.
Do you think it's OK to stick to `int`?

[...]
> +/**
> + * Terminates a thread.
> + *
> + * @param thread_id
> + *    The id of the thread to be cancelled.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.
> + */
> +__rte_experimental
> +int rte_thread_cancel(rte_thread_t thread_id);

What do you think of making this function internal for now?
We don't want applications to rely on this prototype.
To hide it from Doxygen, `/*` comment or #ifndef __DOXYGEN__ can be used.
It is worth noting in commit message
that it's not implemented for Windows and why.

> +
> +/**
> + * Detaches a thread.

Please explain what it means, because detaching is a pthread concept.

> + *
> + * @param thread_id
> + *    The id of the thread to be cancelled.

Not "cancelled".

> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.
> + */
> +__rte_experimental
> +int rte_thread_detach(rte_thread_t thread_id);
> +
> +

Redundant empty line.

>  #ifdef RTE_HAS_CPUSET
>  
>  /**
> diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
> index 6dc3d575c0..5afdd54e15 100644
> --- a/lib/eal/windows/rte_thread.c
> +++ b/lib/eal/windows/rte_thread.c
> @@ -14,6 +14,11 @@ struct eal_tls_key {
>  	DWORD thread_index;
>  };
>  
> +struct thread_routine_ctx {
> +	void* (*start_routine) (void*);
> +	void *routine_args;
> +};
> +
>  /* Translates the most common error codes related to threads */
>  static int
>  thread_translate_win32_error(DWORD error)
> @@ -346,6 +351,163 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
>  	return 0;
>  }
>  
> +static DWORD
> +thread_func_wrapper(void *args)
> +{
> +	struct thread_routine_ctx *pctx = args;
> +	intptr_t func_ret = 0;
> +	struct thread_routine_ctx ctx = { NULL, NULL };
> +
> +	ctx.start_routine = pctx->start_routine;
> +	ctx.routine_args = pctx->routine_args;
> +
> +	free(pctx);
> +
> +	func_ret = (intptr_t)ctx.start_routine(ctx.routine_args);
> +	return (DWORD)func_ret;
> +}
> +
> +int
> +rte_thread_create(rte_thread_t *thread_id,
> +		  const rte_thread_attr_t *thread_attr,
> +		  void *(*thread_func)(void *), void *args)
> +{
> +	int ret = 0;
> +	DWORD tid = 0;
> +	HANDLE thread_handle = NULL;
> +	GROUP_AFFINITY thread_affinity;
> +	struct thread_routine_ctx *ctx = NULL;
> +
> +	ctx = calloc(1, sizeof(*ctx));

Why use `calloc()` for a scalar?

[...]
> +int
> +rte_thread_cancel(rte_thread_t thread_id)
> +{
> +	int ret = 0;
> +	HANDLE thread_handle = NULL;
> +
> +	thread_handle = OpenThread(THREAD_TERMINATE, FALSE, thread_id.opaque_id);
> +	if (thread_handle == NULL) {
> +		ret = thread_log_last_error("OpenThread()");
> +		goto cleanup;
> +	}
> +
> +	/*
> +	 * TODO: Behavior is different between POSIX and Windows threads.
> +	 * POSIX threads wait for a cancellation point.
> +	 * Current Windows emulation kills thread at any point.
> +	 */
> +	ret = TerminateThread(thread_handle, 0);
> +	if (ret != 0) {
> +		ret = thread_log_last_error("TerminateThread()");
> +		goto cleanup;
> +	}
> +
> +cleanup:
> +	if (thread_handle != NULL) {
> +		CloseHandle(thread_handle);
> +		thread_handle = NULL;
> +	}
> +	return ret;
> +}

As we've discussed before, such implementation should never be used.
I suggest removing it for now, otherwise if someone enables the code
calling rte_thread_cancel() for Windows, it will almost certainly lead
to deadlock bugs.

> +
> +int
> +rte_thread_detach(rte_thread_t thread_id)
> +{
> +	(void)thread_id;

RTE_SET_USED/__rte_unused

> +	return ENOTSUP;
> +}
> +

It should return success as the thread is in detached state after the call.

>  int
>  rte_thread_key_create(rte_thread_key *key,
>  		__rte_unused void (*destructor)(void *))


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-06-08 23:04                           ` Dmitry Kozlyuk
  2021-06-09 22:37                             ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:04 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
> index d67b24a563..7bb0d2948c 100644
> --- a/lib/eal/include/rte_thread_types.h
> +++ b/lib/eal/include/rte_thread_types.h
> @@ -7,4 +7,8 @@
>  
>  #include <pthread.h>
>  
> +#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
> +
> +typedef pthread_mutex_t                 rte_thread_mutex_t;
> +
>  #endif /* _RTE_THREAD_TYPES_H_ */
> diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
> index 60e6d94553..c6c8502bfb 100644
> --- a/lib/eal/windows/include/rte_windows_thread_types.h
> +++ b/lib/eal/windows/include/rte_windows_thread_types.h
> @@ -7,4 +7,13 @@
>  
>  #include <rte_windows.h>
>  
> +#define WINDOWS_MUTEX_INITIALIZER               (void*)-1
> +#define RTE_THREAD_MUTEX_INITIALIZER            {WINDOWS_MUTEX_INITIALIZER}
> +
> +struct thread_mutex_t {
> +	void* mutex_id;
> +};
> +
> +typedef struct thread_mutex_t rte_thread_mutex_t;
> +
>  #endif /* _RTE_THREAD_TYPES_H_ */

In previous patches rte_thread content was made opaque and of equal size
for pthread (most implementations) and non-pthread variant.
AFAIU, we agree on the requirement of compatible ABI between variants,
that is, a compiled app can work with any threading variant of DPDK.
Above definition of `rte_thread_mutex_t` does not satisfy it.
Or do we only promise API compatibility?
This is the most important question now.

Also: DPDK should not export names without `rte_` prefix,
i. e. `WINDOWS_MUTEX_INITIALIZER` and `thread_mutex_t`.
Besides, why `_t`?

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API
  2021-06-08  5:50                           ` Narcisa Ana Maria Vasile
  2021-06-08  7:45                             ` David Marchand
@ 2021-06-08 23:08                             ` Dmitry Kozlyuk
  2021-06-18 21:50                               ` Narcisa Ana Maria Vasile
  1 sibling, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-08 23:08 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-07 22:50 (UTC-0700), Narcisa Ana Maria Vasile:
> On Fri, Jun 04, 2021 at 04:44:34PM -0700, Narcisa Ana Maria Vasile wrote:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Rename pthread_* occurrences with the new rte_thread_* API.
> > Enable the new API in the build system.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---  
> 
> I'll send v10. 

Please also run devtools/checkpatches.sh
and fix numerous warnings across the series.
Some patches could be acked already if not this issue.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management
  2021-06-08 23:04                           ` Dmitry Kozlyuk
@ 2021-06-09 22:37                             ` Dmitry Kozlyuk
  2021-06-12  2:39                               ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-09 22:37 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-09 02:04 (UTC+0300), Dmitry Kozlyuk:
> 2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> [...]
> > diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
> > index d67b24a563..7bb0d2948c 100644
> > --- a/lib/eal/include/rte_thread_types.h
> > +++ b/lib/eal/include/rte_thread_types.h
> > @@ -7,4 +7,8 @@
> >  
> >  #include <pthread.h>
> >  
> > +#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
> > +
> > +typedef pthread_mutex_t                 rte_thread_mutex_t;
> > +
> >  #endif /* _RTE_THREAD_TYPES_H_ */
> > diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
> > index 60e6d94553..c6c8502bfb 100644
> > --- a/lib/eal/windows/include/rte_windows_thread_types.h
> > +++ b/lib/eal/windows/include/rte_windows_thread_types.h
> > @@ -7,4 +7,13 @@
> >  
> >  #include <rte_windows.h>
> >  
> > +#define WINDOWS_MUTEX_INITIALIZER               (void*)-1
> > +#define RTE_THREAD_MUTEX_INITIALIZER            {WINDOWS_MUTEX_INITIALIZER}
> > +
> > +struct thread_mutex_t {
> > +	void* mutex_id;
> > +};
> > +
> > +typedef struct thread_mutex_t rte_thread_mutex_t;
> > +
> >  #endif /* _RTE_THREAD_TYPES_H_ */  
> 
> In previous patches rte_thread content was made opaque and of equal size
> for pthread (most implementations) and non-pthread variant.
> AFAIU, we agree on the requirement of compatible ABI between variants,
> that is, a compiled app can work with any threading variant of DPDK.
> Above definition of `rte_thread_mutex_t` does not satisfy it.
> Or do we only promise API compatibility?
> This is the most important question now.

From Windows community call 2021-06-10, for everyone's information.

1. Yes, binary compatibility is a requirement.

2. Static mutex initializer for Windows is tricky (an old topic).
This patch proposes `rte_mutex` to hold a pointer to actual mutex
and use NULL as static initializer, then allocate on first use.
At the same time we want to use the same initializer for pthread variant.
This means it would also need indirection, allocation, and tricky logic.

My opinion:

New threading API can just be without static initilizer.
All it usages in DPDK could be converted to dynamic initialization
either in appropriate function or using `RTE_INIT`.
Maybe create a convenient macro to declare a static mutex and its
initialization code, what do others think?

	RTE_STATIC_MUTEX(private_lock)

Expanding to:

	static RTE_DECLARE_MUTEX(private_lock)
	RTE_DEFINE_MUTEX(private_lock)


Expanding to:

	static rte_mutex private_lock;

	RTE_INIT(__rte_private_lock_init)
	{
		RTE_VERIFY(rte_thread_mutex_init(&private_lock));
	}

As a bonus it removes the need of `rte_*_thread_types.h`.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management
  2021-06-09 22:37                             ` Dmitry Kozlyuk
@ 2021-06-12  2:39                               ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-12  2:39 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Thu, Jun 10, 2021 at 01:37:17AM +0300, Dmitry Kozlyuk wrote:
> 2021-06-09 02:04 (UTC+0300), Dmitry Kozlyuk:
> > 2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> > [...]
> > > diff --git a/lib/eal/include/rte_thread_types.h b/lib/eal/include/rte_thread_types.h
> > > index d67b24a563..7bb0d2948c 100644
> > > --- a/lib/eal/include/rte_thread_types.h
> > > +++ b/lib/eal/include/rte_thread_types.h
> > > @@ -7,4 +7,8 @@
> > >  
> > >  #include <pthread.h>
> > >  
> > > +#define RTE_THREAD_MUTEX_INITIALIZER     PTHREAD_MUTEX_INITIALIZER
> > > +
> > > +typedef pthread_mutex_t                 rte_thread_mutex_t;
> > > +
> > >  #endif /* _RTE_THREAD_TYPES_H_ */
> > > diff --git a/lib/eal/windows/include/rte_windows_thread_types.h b/lib/eal/windows/include/rte_windows_thread_types.h
> > > index 60e6d94553..c6c8502bfb 100644
> > > --- a/lib/eal/windows/include/rte_windows_thread_types.h
> > > +++ b/lib/eal/windows/include/rte_windows_thread_types.h
> > > @@ -7,4 +7,13 @@
> > >  
> > >  #include <rte_windows.h>
> > >  
> > > +#define WINDOWS_MUTEX_INITIALIZER               (void*)-1
> > > +#define RTE_THREAD_MUTEX_INITIALIZER            {WINDOWS_MUTEX_INITIALIZER}
> > > +
> > > +struct thread_mutex_t {
> > > +	void* mutex_id;
> > > +};
> > > +
> > > +typedef struct thread_mutex_t rte_thread_mutex_t;
> > > +
> > >  #endif /* _RTE_THREAD_TYPES_H_ */  
> > 
> > In previous patches rte_thread content was made opaque and of equal size
> > for pthread (most implementations) and non-pthread variant.
> > AFAIU, we agree on the requirement of compatible ABI between variants,
> > that is, a compiled app can work with any threading variant of DPDK.
> > Above definition of `rte_thread_mutex_t` does not satisfy it.
> > Or do we only promise API compatibility?
> > This is the most important question now.
> 
> From Windows community call 2021-06-10, for everyone's information.
> 
> 1. Yes, binary compatibility is a requirement.
> 
> 2. Static mutex initializer for Windows is tricky (an old topic).
> This patch proposes `rte_mutex` to hold a pointer to actual mutex
> and use NULL as static initializer, then allocate on first use.
> At the same time we want to use the same initializer for pthread variant.
> This means it would also need indirection, allocation, and tricky logic.
> 
> My opinion:
> 
> New threading API can just be without static initilizer.
> All it usages in DPDK could be converted to dynamic initialization
> either in appropriate function or using `RTE_INIT`.
> Maybe create a convenient macro to declare a static mutex and its
> initialization code, what do others think?
> 
> 	RTE_STATIC_MUTEX(private_lock)
> 
> Expanding to:
> 
> 	static RTE_DECLARE_MUTEX(private_lock)
> 	RTE_DEFINE_MUTEX(private_lock)
> 
> 
> Expanding to:
> 
> 	static rte_mutex private_lock;
> 
> 	RTE_INIT(__rte_private_lock_init)
> 	{
> 		RTE_VERIFY(rte_thread_mutex_init(&private_lock));
> 	}
> 
> As a bonus it removes the need of `rte_*_thread_types.h`.

Thank you Dmitry, I think this is the best and most elegant solution.
I will use a pointer to represent the mutex:
typedef struct rte_thread_mutex_tag {
	void* mutex_id;
} rte_thread_mutex;

..and use the macro for static initializations as you described.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading
  2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                           ` (9 preceding siblings ...)
  2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                         ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
                                             ` (9 more replies)
  10 siblings, 10 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently relies on a header file that hides the Windows
calls under pthread matched interfaces.
Given that EAL should isolate the environment specifics from
the applications and libraries and mediate all the communication
with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be created
with the affinity and priority described by the attributes object.
If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Add support for pthread_mutex_trylock
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c


Narcisa Vasile (9):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority

 lib/eal/common/eal_common_options.c |  28 +-
 lib/eal/common/eal_internal_cfg.h   |   2 +
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/common/meson.build          |   1 +
 lib/eal/common/rte_thread.c         | 445 +++++++++++++++++++++
 lib/eal/include/rte_thread.h        | 406 ++++++++++++++++++-
 lib/eal/unix/meson.build            |   1 -
 lib/eal/unix/rte_thread.c           |  92 -----
 lib/eal/version.map                 |  20 +
 lib/eal/windows/eal_lcore.c         | 176 ++++++---
 lib/eal/windows/eal_windows.h       |  10 +
 lib/eal/windows/include/sched.h     |   2 +-
 lib/eal/windows/rte_thread.c        | 588 ++++++++++++++++++++++++++--
 13 files changed, 1599 insertions(+), 174 deletions(-)
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 1/9] eal: add basic threading functions
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
                                             ` (8 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index dc711b4240..f2b8063760 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -5,5 +5,4 @@ sources += files(
         'eal_file.c',
         'eal_unix_memory.c',
         'eal_unix_timer.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index fe5c3dac98..43fd9fb6bb 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,9 @@ EXPERIMENTAL {
 	rte_version_release; # WINDOWS_NO_EXPORT
 	rte_version_suffix; # WINDOWS_NO_EXPORT
 	rte_version_year; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 2/9] eal: add thread attributes
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                             ` (7 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 93 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 187 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..032ff73b36 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,30 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +87,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 43fd9fb6bb..a74975c437 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -426,6 +426,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                             ` (6 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 032ff73b36..bf649c2fe6 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -235,9 +235,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 4/9] eal: implement functions for thread affinity management
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (2 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                             ` (5 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index bf649c2fe6..ca4ade60e2 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -87,6 +87,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a74975c437..4f834d8a40 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -430,6 +430,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 478accc1b9..dc5dc8240a 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 5/9] eal: implement thread priority management functions
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (3 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                             ` (4 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 49 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 17 ++++++++++
 lib/eal/version.map          |  1 +
 lib/eal/windows/rte_thread.c | 66 ++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fcebf7097c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,55 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index ca4ade60e2..5514b2f57f 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -215,6 +215,23 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 4f834d8a40..d091aacc47 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -432,6 +432,7 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..fb04718f58 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,72 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 6/9] eal: add thread lifetime management
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (4 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                             ` (3 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 107 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 138 ++++++++++++++++++++++++++++++++
 5 files changed, 304 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fcebf7097c..a0a51bc190 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -144,6 +144,113 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			/*
+			 * Set the inherit scheduler parameter to explicit,
+			 * otherwise the priority attribute is ignored.
+			 */
+			ret = pthread_attr_setinheritsched(attrp,
+					PTHREAD_EXPLICIT_SCHED);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+				goto cleanup;
+			}
+
+			ret = thread_map_priority_to_os_value(
+					thread_attr->priority,
+					&param.sched_priority, &policy
+					);
+			if (ret != 0)
+				goto cleanup;
+
+			ret = pthread_attr_setschedpolicy(attrp, policy);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+				goto cleanup;
+			}
+
+			ret = pthread_attr_setschedparam(attrp, &param);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+				goto cleanup;
+			}
+		}
+
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = pthread_attr_setaffinity_np(attrp,
+					sizeof(thread_attr->cpuset),
+					&thread_attr->cpuset);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5514b2f57f..098c3ba343 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -213,6 +214,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index d091aacc47..b6d7028d94 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -433,6 +433,9 @@ EXPERIMENTAL {
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index fb04718f58..e5e420fadd 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -309,6 +314,139 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	unsigned long *func_ret = NULL;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (unsigned long *)ctx.thread_func(ctx.routine_args);
+	return *func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			ret = rte_thread_set_priority(*thread_id,
+						      thread_attr->priority);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 7/9] eal: implement functions for mutex management
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (5 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                             ` (2 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 +++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 94 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 53 ++++++++++++++++++++
 4 files changed, 212 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index a0a51bc190..ebae4a8af1 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -251,6 +251,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 098c3ba343..7e813b573d 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -56,6 +56,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -268,6 +288,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -287,6 +329,58 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index b6d7028d94..75bfa5c02e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -436,6 +436,10 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index e5e420fadd..23f00cfba2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -447,6 +447,59 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 8/9] eal: implement functions for thread barrier management
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (6 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 9/9] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ebae4a8af1..3fdb267337 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -312,6 +312,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7e813b573d..40da83467b 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -76,6 +76,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -381,6 +393,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 75bfa5c02e..6645f60a78 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -440,6 +440,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_lock;
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 23f00cfba2..b2ff16f51f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -500,6 +500,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v10 9/9] eal: add EAL argument for setting thread priority
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (7 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-06-18 21:26                           ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:26 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 --thread-prio normal -- -q 8 -p ffff

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ff5861b5f3..9d29696b84 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2088,6 +2113,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions
  2021-06-08 23:03                           ` Dmitry Kozlyuk
@ 2021-06-18 21:30                             ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:30 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Wed, Jun 09, 2021 at 02:03:48AM +0300, Dmitry Kozlyuk wrote:
> 2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Use a portable, type-safe representation for the thread identifier.
> > Add functions for comparing thread ids and obtaining the thread id
> > for the current thread.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
> >  lib/eal/common/rte_thread.c                   | 105 ++++++++++++++++++
> >  lib/eal/include/rte_thread.h                  |  53 +++++++--
> >  lib/eal/include/rte_thread_types.h            |  10 ++
> >  .../include/rte_windows_thread_types.h        |  10 ++
> >  lib/eal/windows/rte_thread.c                  |  17 +++
> >  5 files changed, 186 insertions(+), 9 deletions(-)
> >  create mode 100644 lib/eal/common/rte_thread.c
> >  create mode 100644 lib/eal/include/rte_thread_types.h
> >  create mode 100644 lib/eal/windows/include/rte_windows_thread_types.h
> 
> It is strange that new files are being filled in the series, but are neither
> compiled nor installed until the last patch. Any reason not to replace
> lib/eal/unix/rte_thread.c starting from this patch?
> 
Replaced unix/rte_thread.c starting from here.

> A better name for rte_thread_types.h would be rte_posix_thread_types.h
> to indicate this file is not really common.
> 
> > 
> > +rte_thread_t
> > +rte_thread_self(void)
> > +{
> > +	rte_thread_t thread_id = { 0 };
> 
> (Applies to entire series.)
> Please do not initialize variables when you intend to overwrite them.
> This prevents compiler from reporting code paths where the variable is used
> before a proper assignment.

Thanks for the explanation, Dmitry!
> 
> 
> [...]
> > diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
> > index 8be8ed8f36..347df1a6ae 100644
> directly, see lib/eal/$arch/rte_atomic_64.h for examples.
> 
> Note that rte_*_thread_types.h should be `indirect_headers`, not `headers`
> in `meson.build` so that they're not checked by `buildtools/chkincs` when is
> gets enabled for Windows. This is especially
> true for lib/eal/common/rte_thread.h that cannot work without pthread.
> 
> However, in later patches these headers only contain mutex bits,
> see the comment to pathc 07/10 about them. Maybe we don't need these files
> after all.

Agreed, I was able to remove them after reimplementing the mutex functions.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management
  2021-06-08 23:04                           ` Dmitry Kozlyuk
@ 2021-06-18 21:41                             ` Narcisa Ana Maria Vasile
  2021-06-18 22:48                               ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:41 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Wed, Jun 09, 2021 at 02:04:09AM +0300, Dmitry Kozlyuk wrote:
> 2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> [...]
> > diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
> > index 5c54cd9d67..1d481b9ad5 100644
> > --- a/lib/eal/include/rte_thread.h
> > +++ b/lib/eal/include/rte_thread.h
> > +__rte_experimental
> > +int rte_thread_create(rte_thread_t *thread_id,
> > +		      const rte_thread_attr_t *thread_attr,
> > +		      void *(*thread_func)(void *), void *args);
> 
> 1. Thread function prototype is used at least in 4 places,
> maybe give it a name, like `rte_thread_func`?
> 
> 2. We can't easily support it's `void*` return type on Windows,
> because it doesn't fit in DWORD. In `rte_thread_join` below you use `int`.
> All `pthread_join` usages in DPDK ignore return value, but I'd rather keep it.
> Do you think it's OK to stick to `int`?
> 
Thank you, I agree that we should keep it. I've changed it to unsigned long
to fit with Windows's DWORD as well.

> [...]
> > +/**
> > + * Terminates a thread.
> > + *
> > + * @param thread_id
> > + *    The id of the thread to be cancelled.
> > + *
> > + * @return
> > + *   On success, return 0.
> > + *   On failure, return a positive errno-style error number.
> > + */
> > +__rte_experimental
> > +int rte_thread_cancel(rte_thread_t thread_id);
> 
> What do you think of making this function internal for now?
> We don't want applications to rely on this prototype.
> To hide it from Doxygen, `/*` comment or #ifndef __DOXYGEN__ can be used.
> It is worth noting in commit message
> that it's not implemented for Windows and why.
> 
 Thank you, I've removed it for now.
> > +
> > +	HANDLE thread_handle = NULL;
> > +	GROUP_AFFINITY thread_affinity;
> > +	struct thread_routine_ctx *ctx = NULL;
> > +
> > +	ctx = calloc(1, sizeof(*ctx));
> 
> Why use `calloc()` for a scalar?

ctx is pointer to struct that holds the thread function pointer and its arguments.
Did I misunderstand what you meant?
> 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management
  2021-06-08 23:03                           ` Dmitry Kozlyuk
@ 2021-06-18 21:44                             ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:44 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Wed, Jun 09, 2021 at 02:03:57AM +0300, Dmitry Kozlyuk wrote:
> 2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
> [...]
> > diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
> > index 6ea1dc2a05..9e74a538c2 100644
> > --- a/lib/eal/windows/rte_thread.c
> > +++ b/lib/eal/windows/rte_thread.c
> > @@ -7,7 +7,8 @@
> >  #include <rte_errno.h>
> >  #include <rte_debug.h>
> >  #include <rte_thread.h>
> > -#include <rte_windows.h>
> > +
> > +#include "eal_windows.h"
> >  
> >  struct eal_tls_key {
> >  	DWORD thread_index;
> > @@ -77,6 +78,130 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
> >  	return t1.opaque_id == t2.opaque_id;
> >  }
> >  
> > +static int
> > +rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
> > +			       PGROUP_AFFINITY affinity)
> > +{
> > +	int ret = 0;
> > +	PGROUP_AFFINITY cpu_affinity = NULL;
> > +
> > +	memset(affinity, 0, sizeof(GROUP_AFFINITY));
> > +	affinity->Group = (USHORT)-1;
> > +
> > +	/* Check that all cpus of the set belong to the same processor group and
> > +	 * accumulate thread affinity to be applied.
> > +	 */
> > +	for (unsigned int cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
> > +		if (!CPU_ISSET(cpu_idx, cpuset))
> > +			continue;
> > +
> > +		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
> > +
> > +		if (affinity->Group == (USHORT)-1) {
> > +			affinity->Group = cpu_affinity->Group;
> > +		} else if (affinity->Group != cpu_affinity->Group) {
> > +			ret = EINVAL;
> > +			goto cleanup;
> > +		}
> > +
> > +		affinity->Mask |= cpu_affinity->Mask;
> > +	}
> > +
> > +	if (affinity->Mask == 0) {
> > +		ret = EINVAL;
> > +		goto cleanup;
> > +	}
> > +
> > +cleanup:
> > +	return ret;
> > +}
> 
> For v5 I asked a question that possibly got lost among other comments.
> Repeating the question for convenience:
> 
> 	Just to be clear: is it a kernel limitation that a thread can only
> 	run on cores of one processor group, or do we impose it so that API
> 	is atomic (transactional), i.e. because one of multiple
> 	SetThreadGroupAffinity() calls may fail and leave thread partially
> 	affinitized?
The second reason (to ensure full affinitization). I am not aware of a kernel limitation,
but I'll double check with Dmitry as we co-engineered this patch.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API
  2021-06-08 23:08                             ` Dmitry Kozlyuk
@ 2021-06-18 21:50                               ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:50 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Wed, Jun 09, 2021 at 02:08:22AM +0300, Dmitry Kozlyuk wrote:
> 2021-06-07 22:50 (UTC-0700), Narcisa Ana Maria Vasile:
> > On Fri, Jun 04, 2021 at 04:44:34PM -0700, Narcisa Ana Maria Vasile wrote:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > > 
> > > Rename pthread_* occurrences with the new rte_thread_* API.
> > > Enable the new API in the build system.
> > > 
> > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > > ---  
> > 
> > I'll send v10. 
> 
> Please also run devtools/checkpatches.sh
> and fix numerous warnings across the series.
> Some patches could be acked already if not this issue.

Thanks, I've fixed the CS errors.
There will be a few warnings that I can't fix (the negative errors for example).

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API
  2021-06-08  7:45                             ` David Marchand
@ 2021-06-18 21:53                               ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-06-18 21:53 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, Thomas Monjalon, Dmitry Kozlyuk, Khoa To, navasile,
	Dmitry Malloy (MESHCHANINOV),
	roretzla, Tal Shnaiderman, Omar Cardona, Bruce Richardson,
	Pallavi Kadam

On Tue, Jun 08, 2021 at 09:45:44AM +0200, David Marchand wrote:
> On Tue, Jun 8, 2021 at 7:50 AM Narcisa Ana Maria Vasile
> <navasile@linux.microsoft.com> wrote:
> >
> > On Fri, Jun 04, 2021 at 04:44:34PM -0700, Narcisa Ana Maria Vasile wrote:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > >
> > > Rename pthread_* occurrences with the new rte_thread_* API.
> > > Enable the new API in the build system.
> > >
> > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > > ---
> >
> > I'll send v10.
> > Can someone please help with an example on how to check for ABI breaks? Thank you!
> >
> > I've run:
> > DPDK_ABI_REF_VERSION=v21.05 DPDK_ABI_REF_DIR=~/ref ./devtools/test-meson-builds.sh
> > which doesn't give any warnings about the ABI break.
> 
> This should work the way you tried if you have working toolchains and
> libabigail installed.
> Something is off in your env.
> 
> Side note: ovsrobot is out those days (we have some trouble in one of
> RH labs and it happens ovsrobot is hosted there), but you could try
> with a github repo of yours + GHA, and the ABI failure should be
> caught too.
> 
> 
> I just tried on my rhel7 (gcc 4.8.5 + libabigail 1.8.2) with your
> series applied.
> $ DPDK_ABI_REF_VERSION=v21.05
> DPDK_ABI_REF_DIR=~/git/pub/dpdk.org/reference
> ./devtools/test-meson-builds.sh
> ...
> Error: ABI issue reported for 'abidiff --suppr
> /home/dmarchan/git/pub/dpdk.org/devtools/../devtools/libabigail.abignore
> --no-added-syms --headers-dir1
> /home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/usr/local/include
> --headers-dir2 /home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/usr/local/include
> /home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/dump/librte_eal.dump
> /home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/dump/librte_eal.dump'
> ABIDIFF_ABI_CHANGE, this change requires a review (abidiff flagged
> this as a potential issue).
> 
> 
> $ abidiff --suppr
> /home/dmarchan/git/pub/dpdk.org/devtools/../devtools/libabigail.abignore
> --no-added-syms --headers-dir1
> /home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/usr/local/include
> --headers-dir2 /home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/usr/local/include
> /home/dmarchan/git/pub/dpdk.org/reference/v21.05/build-gcc-shared/dump/librte_eal.dump
> /home/dmarchan/git/pub/dpdk.org/build-gcc-shared/install/dump/librte_eal.dump
> Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0
> Added (20 filtered out) functions
> Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
> 
> 2 functions with some indirect sub-type change:
> 
>   [C] 'function int rte_ctrl_thread_create(pthread_t*, const char*,
> const pthread_attr_t*, void* (void*)*, void*)' at rte_lcore.h:443:1
> has some indirect sub-type changes:
>     parameter 1 of type 'pthread_t*' changed:
>       in pointed to type 'typedef pthread_t' at rte_thread.h:42:1:
>         typedef name changed from pthread_t to rte_thread_t at rte_thread.h:42:1
>         underlying type 'unsigned long int' changed:
>           entity changed from 'unsigned long int' to 'struct
> rte_thread_tag' at rte_thread.h:40:1
>           type size hasn't changed
>     parameter 3 of type 'const pthread_attr_t*' changed:
>       in pointed to type 'const pthread_attr_t':
>         'const pthread_attr_t' changed to 'const rte_thread_attr_t'
> 
>   [C] 'function int rte_thread_setname(pthread_t, const char*)' at
> rte_lcore.h:377:1 has some indirect sub-type changes:
>     parameter 1 of type 'typedef pthread_t' changed:
>       typedef name changed from pthread_t to rte_thread_t at rte_thread.h:42:1
>       underlying type 'unsigned long int' changed:
>         entity changed from 'unsigned long int' to 'struct
> rte_thread_tag' at rte_thread.h:40:1
>         type size hasn't changed
> 
> 
> 
> Can you check that in your env build-gcc-shared/ and the build
> directory for references are configured with debug symbols?
> You should see:
> $ meson configure build-gcc-shared | awk '$1=="buildtype" {print $2}'
> debugoptimized
> $ meson configure reference/v21.05/build | awk '$1=="buildtype" {print $2}'
> debugoptimized
> 
> 
Thank you very much David! There was something wrong with my local reference.
Using your commands, I am able to run the tools now.
> 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management
  2021-06-18 21:41                             ` Narcisa Ana Maria Vasile
@ 2021-06-18 22:48                               ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-06-18 22:48 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-06-18 14:41 (UTC-0700), Narcisa Ana Maria Vasile:
> On Wed, Jun 09, 2021 at 02:04:09AM +0300, Dmitry Kozlyuk wrote:
> > 2021-06-04 16:44 (UTC-0700), Narcisa Ana Maria Vasile:
[...]
> > > +
> > > +	HANDLE thread_handle = NULL;
> > > +	GROUP_AFFINITY thread_affinity;
> > > +	struct thread_routine_ctx *ctx = NULL;
> > > +
> > > +	ctx = calloc(1, sizeof(*ctx));  
> > 
> > Why use `calloc()` for a scalar?  
> 
> ctx is pointer to struct that holds the thread function pointer and its arguments.
> Did I misunderstand what you meant?

`calloc(size_t n, size_t size)` mainly exists for safe array allocations,
because multiplication in `malloc(n * size)` may overflow. You are allocating
a singular value, i. e. a scalar, so the choice of `calloc()` over `malloc()`
raises questions. Nevertheless, it is harmless and works correctly. Consider
it a nit.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading
  2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                             ` (8 preceding siblings ...)
  2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 9/9] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                           ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
                                               ` (10 more replies)
  9 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Add support for pthread_mutex_trylock
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c


Narcisa Vasile (10):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Add unit tests for thread API

 app/test/meson.build                |   2 +
 app/test/test_threads.c             | 419 ++++++++++++++++++++
 lib/eal/common/eal_common_options.c |  28 +-
 lib/eal/common/eal_internal_cfg.h   |   2 +
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/common/meson.build          |   1 +
 lib/eal/common/rte_thread.c         | 445 +++++++++++++++++++++
 lib/eal/include/rte_thread.h        | 406 ++++++++++++++++++-
 lib/eal/unix/meson.build            |   1 -
 lib/eal/unix/rte_thread.c           |  92 -----
 lib/eal/version.map                 |  20 +
 lib/eal/windows/eal_lcore.c         | 176 ++++++---
 lib/eal/windows/eal_windows.h       |  10 +
 lib/eal/windows/include/sched.h     |   2 +-
 lib/eal/windows/rte_thread.c        | 588 ++++++++++++++++++++++++++--
 15 files changed, 2020 insertions(+), 174 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 01/10] eal: add basic threading functions
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                               ` (9 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 887012d02a..ba7dcda664 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -426,6 +426,9 @@ EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 02/10] eal: add thread attributes
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                               ` (8 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 93 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 187 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..032ff73b36 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,30 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +87,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ba7dcda664..9ffa5eb15e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 03/10] eal/windows: translate Windows errors to errno-style errors
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                               ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 032ff73b36..bf649c2fe6 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -235,9 +235,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 04/10] eal: implement functions for thread affinity management
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (2 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                               ` (6 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index bf649c2fe6..ca4ade60e2 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -87,6 +87,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 9ffa5eb15e..7ed4cd779e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -433,6 +433,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 7cc811485d..c1f8699777 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 05/10] eal: implement thread priority management functions
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (3 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                               ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 49 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 17 ++++++++++
 lib/eal/version.map          |  1 +
 lib/eal/windows/rte_thread.c | 66 ++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fcebf7097c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,55 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index ca4ade60e2..5514b2f57f 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -215,6 +215,23 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 7ed4cd779e..df01bbbbe4 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -435,6 +435,7 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..fb04718f58 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,72 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 06/10] eal: add thread lifetime management
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (4 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                               ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 107 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 138 ++++++++++++++++++++++++++++++++
 5 files changed, 304 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fcebf7097c..a0a51bc190 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -144,6 +144,113 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			/*
+			 * Set the inherit scheduler parameter to explicit,
+			 * otherwise the priority attribute is ignored.
+			 */
+			ret = pthread_attr_setinheritsched(attrp,
+					PTHREAD_EXPLICIT_SCHED);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+				goto cleanup;
+			}
+
+			ret = thread_map_priority_to_os_value(
+					thread_attr->priority,
+					&param.sched_priority, &policy
+					);
+			if (ret != 0)
+				goto cleanup;
+
+			ret = pthread_attr_setschedpolicy(attrp, policy);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+				goto cleanup;
+			}
+
+			ret = pthread_attr_setschedparam(attrp, &param);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+				goto cleanup;
+			}
+		}
+
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = pthread_attr_setaffinity_np(attrp,
+					sizeof(thread_attr->cpuset),
+					&thread_attr->cpuset);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5514b2f57f..098c3ba343 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -213,6 +214,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index df01bbbbe4..02994dd3fb 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -436,6 +436,9 @@ EXPERIMENTAL {
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index fb04718f58..e5e420fadd 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -309,6 +314,139 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	unsigned long *func_ret = NULL;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (unsigned long *)ctx.thread_func(ctx.routine_args);
+	return *func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			ret = rte_thread_set_priority(*thread_id,
+						      thread_attr->priority);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 07/10] eal: implement functions for mutex management
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (5 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                               ` (3 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 +++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 94 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 53 ++++++++++++++++++++
 4 files changed, 212 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index a0a51bc190..ebae4a8af1 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -251,6 +251,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 098c3ba343..7e813b573d 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -56,6 +56,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -268,6 +288,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -287,6 +329,58 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 02994dd3fb..a1c7a8e87d 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -439,6 +439,10 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index e5e420fadd..23f00cfba2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -447,6 +447,59 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 08/10] eal: implement functions for thread barrier management
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (6 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                               ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ebae4a8af1..3fdb267337 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -312,6 +312,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7e813b573d..40da83467b 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -76,6 +76,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -381,6 +393,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a1c7a8e87d..c081fdd96c 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -443,6 +443,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_lock;
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 23f00cfba2..b2ff16f51f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -500,6 +500,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 09/10] eal: add EAL argument for setting thread priority
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (7 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 --thread-prio normal -- -q 8 -p ffff

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ff5861b5f3..9d29696b84 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2088,6 +2113,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v11 10/10] Add unit tests for thread API
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (8 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-07-30 22:31                             ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-07-30 22:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |   2 +
 app/test/test_threads.c | 419 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 421 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index a7611686ad..6fe8b02459 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -140,6 +140,7 @@ test_sources = files(
         'test_table_tables.c',
         'test_tailq.c',
         'test_thash.c',
+	'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -276,6 +277,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+	['threads_autotest, true'],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..ce614942eb
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,419 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <pthread.h>
+
+#include <rte_thread.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+#define TEST_THREADS_LOG(func) \
+		printf("Error at line %d. %s failed!\n", __LINE__, func)
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {0};
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			break;
+		}
+	}
+
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			return -1;
+		}
+
+		if (rte_thread_equal(threads_ids[j], self_ids[j]) == 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_context {
+	rte_thread_barrier *barrier;
+	size_t *thread_count;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+
+	struct thread_context *ctx = arg;
+
+	(void)__atomic_add_fetch(ctx->thread_count, 1, __ATOMIC_RELAXED);
+
+	if (rte_thread_barrier_wait(ctx->barrier) > 0)
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_context ctx[THREADS_COUNT] = {0};
+	rte_thread_barrier barrier;
+	size_t count = 0;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_barrier_init(&barrier, THREADS_COUNT + 1);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].thread_count = &count;
+		ctx[i].barrier = &barrier;
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_barrier, &ctx[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+	ret = rte_thread_barrier_wait(ctx->barrier);
+	if (ret > 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+		ret = -1;
+		goto error;
+	}
+
+	if (count != i) {
+		ret = -1;
+		printf("Error, expected thread count(%zu) to be equal "
+			"to the number of threads that wait at the barrier(%zu)\n",
+			count, i);
+		goto error;
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_destroy()");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static size_t val;
+
+static void *
+thread_loop_mutex(void *arg)
+{
+	rte_thread_mutex *mutex = arg;
+
+	rte_thread_mutex_lock(mutex);
+	val++;
+	rte_thread_mutex_unlock(mutex);
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_mutex mutex;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	/*
+	 * The value that each thread will increment while holding the mutex.
+	 */
+	val = 0;
+
+	ret = rte_thread_mutex_init(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_mutex, &mutex) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+		}
+	}
+
+	ret = rte_thread_mutex_destroy(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_destroy()");
+		ret = -1;
+	}
+
+	if (i != val) {
+		printf("Unexpected value: %zu!. Expected %zu. "
+			"Each thread should increment the value once.\n",
+			val, i);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_affinity_ctx {
+	size_t idx;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+			&cpuset) != 0) {
+		ctx->result = 1;
+		TEST_THREADS_LOG("pthread_getaffinity_np()");
+		return NULL;
+	}
+
+	if (!CPU_ISSET(ctx->idx, &cpuset)) {
+		ctx->result = 1;
+		printf("CPU %zu should be set for thread %zu\n",
+			ctx->idx, ctx->idx);
+		return NULL;
+	}
+
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (i != ctx->idx && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			printf("CPU %zu should not be set for thread %zu\n",
+				i, ctx->idx);
+			return NULL;
+		}
+	}
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {0};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		CPU_ZERO(&cpuset);
+		CPU_SET(i, &cpuset);
+
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("rte_thread_attr_set_affinity()");
+			goto error;
+		}
+
+		ctx[i].idx = i;
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity,
+				&ctx[i]) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+
+		if (ctx[j].result != 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	size_t j;
+	int ret = 0;
+	int policy;
+	struct sched_param param;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_set_priority()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		ret = pthread_getschedparam(
+				(pthread_t)threads_ids[i].opaque_id,
+				&policy, &param);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("pthread_getschedparam()");
+			goto error;
+		}
+
+		if (policy != SCHED_OTHER || param.sched_priority != 0) {
+			ret = -1;
+			printf("Unexpected priority: %d or policy: %d\n",
+					param.sched_priority, SCHED_OTHER);
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_detach(threads_ids[j]);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_detach()");
+			return -1;
+		}
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading
  2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                               ` (9 preceding siblings ...)
  2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                             ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                 ` (10 more replies)
  10 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Add support for pthread_mutex_trylock
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c


Narcisa Vasile (10):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Add unit tests for thread API

 app/test/meson.build                |   2 +
 app/test/test_threads.c             | 419 ++++++++++++++++++++
 lib/eal/common/eal_common_options.c |  28 +-
 lib/eal/common/eal_internal_cfg.h   |   2 +
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/common/meson.build          |   1 +
 lib/eal/common/rte_thread.c         | 445 +++++++++++++++++++++
 lib/eal/include/rte_thread.h        | 406 ++++++++++++++++++-
 lib/eal/unix/meson.build            |   1 -
 lib/eal/unix/rte_thread.c           |  92 -----
 lib/eal/version.map                 |  20 +
 lib/eal/windows/eal_lcore.c         | 176 ++++++---
 lib/eal/windows/eal_windows.h       |  10 +
 lib/eal/windows/include/sched.h     |   2 +-
 lib/eal/windows/rte_thread.c        | 588 ++++++++++++++++++++++++++--
 15 files changed, 2020 insertions(+), 174 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 21:08                                 ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                                 ` (9 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 887012d02a..ba7dcda664 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -426,6 +426,9 @@ EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 02/10] eal: add thread attributes
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                 ` (8 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 93 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 187 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..032ff73b36 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,30 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +87,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ba7dcda664..9ffa5eb15e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 03/10] eal/windows: translate Windows errors to errno-style errors
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                 ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 032ff73b36..bf649c2fe6 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -235,9 +235,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 04/10] eal: implement functions for thread affinity management
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (2 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                 ` (6 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index bf649c2fe6..ca4ade60e2 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -87,6 +87,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 9ffa5eb15e..7ed4cd779e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -433,6 +433,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 7cc811485d..c1f8699777 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 05/10] eal: implement thread priority management functions
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (3 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                 ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 49 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 17 ++++++++++
 lib/eal/version.map          |  1 +
 lib/eal/windows/rte_thread.c | 66 ++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fcebf7097c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,55 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index ca4ade60e2..5514b2f57f 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -215,6 +215,23 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 7ed4cd779e..df01bbbbe4 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -435,6 +435,7 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..fb04718f58 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,72 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 06/10] eal: add thread lifetime management
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (4 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                                 ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 107 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 138 ++++++++++++++++++++++++++++++++
 5 files changed, 304 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fcebf7097c..a0a51bc190 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -144,6 +144,113 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			/*
+			 * Set the inherit scheduler parameter to explicit,
+			 * otherwise the priority attribute is ignored.
+			 */
+			ret = pthread_attr_setinheritsched(attrp,
+					PTHREAD_EXPLICIT_SCHED);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+				goto cleanup;
+			}
+
+			ret = thread_map_priority_to_os_value(
+					thread_attr->priority,
+					&param.sched_priority, &policy
+					);
+			if (ret != 0)
+				goto cleanup;
+
+			ret = pthread_attr_setschedpolicy(attrp, policy);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+				goto cleanup;
+			}
+
+			ret = pthread_attr_setschedparam(attrp, &param);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+				goto cleanup;
+			}
+		}
+
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = pthread_attr_setaffinity_np(attrp,
+					sizeof(thread_attr->cpuset),
+					&thread_attr->cpuset);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5514b2f57f..098c3ba343 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -213,6 +214,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index df01bbbbe4..02994dd3fb 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -436,6 +436,9 @@ EXPERIMENTAL {
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index fb04718f58..e5e420fadd 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -309,6 +314,139 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	unsigned long *func_ret = NULL;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (unsigned long *)ctx.thread_func(ctx.routine_args);
+	return *func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			ret = rte_thread_set_priority(*thread_id,
+						      thread_attr->priority);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 07/10] eal: implement functions for mutex management
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (5 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                                 ` (3 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 +++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 94 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 53 ++++++++++++++++++++
 4 files changed, 212 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index a0a51bc190..ebae4a8af1 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -251,6 +251,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 098c3ba343..7e813b573d 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -56,6 +56,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -268,6 +288,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -287,6 +329,58 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 02994dd3fb..a1c7a8e87d 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -439,6 +439,10 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index e5e420fadd..23f00cfba2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -447,6 +447,59 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 08/10] eal: implement functions for thread barrier management
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (6 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                                 ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ebae4a8af1..3fdb267337 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -312,6 +312,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7e813b573d..40da83467b 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -76,6 +76,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -381,6 +393,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a1c7a8e87d..c081fdd96c 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -443,6 +443,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_lock;
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 23f00cfba2..b2ff16f51f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -500,6 +500,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 09/10] eal: add EAL argument for setting thread priority
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (7 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 --thread-prio normal -- -q 8 -p ffff

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ff5861b5f3..9d29696b84 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2088,6 +2113,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v12 10/10] Add unit tests for thread API
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (8 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-08-02 17:32                               ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 17:32 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |   2 +
 app/test/test_threads.c | 419 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 421 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index a7611686ad..bfa60773bd 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -140,6 +140,7 @@ test_sources = files(
         'test_table_tables.c',
         'test_tailq.c',
         'test_thash.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -276,6 +277,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest, true'],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..beaa303506
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,419 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <pthread.h>
+
+#include <rte_thread.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+#define TEST_THREADS_LOG(func) \
+		printf("Error at line %d. %s failed!\n", __LINE__, func)
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			break;
+		}
+	}
+
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			return -1;
+		}
+
+		if (rte_thread_equal(threads_ids[j], self_ids[j]) == 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_context {
+	rte_thread_barrier *barrier;
+	size_t *thread_count;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+
+	struct thread_context *ctx = arg;
+
+	(void)__atomic_add_fetch(ctx->thread_count, 1, __ATOMIC_RELAXED);
+
+	if (rte_thread_barrier_wait(ctx->barrier) > 0)
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_context ctx[THREADS_COUNT] = {};
+	rte_thread_barrier barrier;
+	size_t count = 0;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_barrier_init(&barrier, THREADS_COUNT + 1);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].thread_count = &count;
+		ctx[i].barrier = &barrier;
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_barrier, &ctx[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+	ret = rte_thread_barrier_wait(ctx->barrier);
+	if (ret > 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+		ret = -1;
+		goto error;
+	}
+
+	if (count != i) {
+		ret = -1;
+		printf("Error, expected thread count(%zu) to be equal "
+			"to the number of threads that wait at the barrier(%zu)\n",
+			count, i);
+		goto error;
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_destroy()");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static size_t val;
+
+static void *
+thread_loop_mutex(void *arg)
+{
+	rte_thread_mutex *mutex = arg;
+
+	rte_thread_mutex_lock(mutex);
+	val++;
+	rte_thread_mutex_unlock(mutex);
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_mutex mutex;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	/*
+	 * The value that each thread will increment while holding the mutex.
+	 */
+	val = 0;
+
+	ret = rte_thread_mutex_init(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_mutex, &mutex) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+		}
+	}
+
+	ret = rte_thread_mutex_destroy(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_destroy()");
+		ret = -1;
+	}
+
+	if (i != val) {
+		printf("Unexpected value: %zu!. Expected %zu. "
+			"Each thread should increment the value once.\n",
+			val, i);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_affinity_ctx {
+	size_t idx;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+			&cpuset) != 0) {
+		ctx->result = 1;
+		TEST_THREADS_LOG("pthread_getaffinity_np()");
+		return NULL;
+	}
+
+	if (!CPU_ISSET(ctx->idx, &cpuset)) {
+		ctx->result = 1;
+		printf("CPU %zu should be set for thread %zu\n",
+			ctx->idx, ctx->idx);
+		return NULL;
+	}
+
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (i != ctx->idx && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			printf("CPU %zu should not be set for thread %zu\n",
+				i, ctx->idx);
+			return NULL;
+		}
+	}
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		CPU_ZERO(&cpuset);
+		CPU_SET(i, &cpuset);
+
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("rte_thread_attr_set_affinity()");
+			goto error;
+		}
+
+		ctx[i].idx = i;
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity,
+				&ctx[i]) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+
+		if (ctx[j].result != 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	size_t j;
+	int ret = 0;
+	int policy;
+	struct sched_param param;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_set_priority()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		ret = pthread_getschedparam(
+				(pthread_t)threads_ids[i].opaque_id,
+				&policy, &param);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("pthread_getschedparam()");
+			goto error;
+		}
+
+		if (policy != SCHED_OTHER || param.sched_priority != 0) {
+			ret = -1;
+			printf("Unexpected priority: %d or policy: %d\n",
+					param.sched_priority, SCHED_OTHER);
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_detach(threads_ids[j]);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_detach()");
+			return -1;
+		}
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-08-02 21:08                                 ` Narcisa Ana Maria Vasile
  2021-08-02 21:37                                   ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-02 21:08 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

On Mon, Aug 02, 2021 at 10:32:17AM -0700, Narcisa Ana Maria Vasile wrote:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Use a portable, type-safe representation for the thread identifier.
> Add functions for comparing thread ids and obtaining the thread id
> for the current thread.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/eal/common/meson.build            |  1 +
>  lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
>  lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
>  lib/eal/unix/meson.build              |  1 -
>  lib/eal/version.map                   |  3 ++
>  lib/eal/windows/rte_thread.c          | 17 ++++++++
>  6 files changed, 95 insertions(+), 32 deletions(-)
>  rename lib/eal/{unix => common}/rte_thread.c (66%)
> 
> diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build

Hello, 

I see the following error on this patch:

ninja: error: loading 'build.ninja': No such file or directory

https://lab.dpdk.org/results/dashboard/patchsets/18090/

Locally, the build succeedes.
How can I see more information about this build error?

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions
  2021-08-02 21:08                                 ` Narcisa Ana Maria Vasile
@ 2021-08-02 21:37                                   ` Dmitry Kozlyuk
  2021-08-03 15:11                                     ` [dpdk-dev] [dpdk-ci] " Owen Hilyard
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-08-02 21:37 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam, ci

+ ci@dpdk.org

2021-08-02 14:08 (UTC-0700), Narcisa Ana Maria Vasile:
> On Mon, Aug 02, 2021 at 10:32:17AM -0700, Narcisa Ana Maria Vasile wrote:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Use a portable, type-safe representation for the thread identifier.
> > Add functions for comparing thread ids and obtaining the thread id
> > for the current thread.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
> >  lib/eal/common/meson.build            |  1 +
> >  lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
> >  lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
> >  lib/eal/unix/meson.build              |  1 -
> >  lib/eal/version.map                   |  3 ++
> >  lib/eal/windows/rte_thread.c          | 17 ++++++++
> >  6 files changed, 95 insertions(+), 32 deletions(-)
> >  rename lib/eal/{unix => common}/rte_thread.c (66%)
> > 
> > diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build  
> 
> Hello, 
> 
> I see the following error on this patch:
> 
> ninja: error: loading 'build.ninja': No such file or directory
> 
> https://lab.dpdk.org/results/dashboard/patchsets/18090/
> 
> Locally, the build succeedes.
> How can I see more information about this build error?

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [dpdk-ci] [PATCH v12 01/10] eal: add basic threading functions
  2021-08-02 21:37                                   ` Dmitry Kozlyuk
@ 2021-08-03 15:11                                     ` Owen Hilyard
  2021-08-03 15:38                                       ` Dmitry Kozlyuk
  0 siblings, 1 reply; 290+ messages in thread
From: Owen Hilyard @ 2021-08-03 15:11 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Narcisa Ana Maria Vasile, dev, Thomas Monjalon, Khoa To,
	navasile, Dmitry Malloy, Tyler Retzlaff, talshn, Omar Cardona,
	Richardson, Bruce, David Marchand, pallavi.kadam, ci

It seems like meson encountered an error when building

app/test/meson.build:472:11: ERROR: Index 1 out of bounds of array of size
> 1.
>
> A full log can be found at
> /home-local/jenkins-local/jenkins-agent/workspace/Apply-Custom-Patch-Set/dpdk/build/meson-logs/meson-log.txt
> ninja: error: loading 'build.ninja': No such file or directory
>

I can also reproduce the issue building locally (Meson version: 0.58.1):
1. Get the DPDK main branch (f12b844b54f4ea7908ecb08ade04c7366ede031d)
2. apply all patches
3. meson $BUILD_DIR

Meson doesn't really give any extra information aside from that, but
looking at the build file, it looks like one of the fast_tests has no
arguments and at least one is expected.

On Mon, Aug 2, 2021 at 5:37 PM Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
wrote:

> + ci@dpdk.org
>
> 2021-08-02 14:08 (UTC-0700), Narcisa Ana Maria Vasile:
> > On Mon, Aug 02, 2021 at 10:32:17AM -0700, Narcisa Ana Maria Vasile wrote:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > >
> > > Use a portable, type-safe representation for the thread identifier.
> > > Add functions for comparing thread ids and obtaining the thread id
> > > for the current thread.
> > >
> > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > > ---
> > >  lib/eal/common/meson.build            |  1 +
> > >  lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
> > >  lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
> > >  lib/eal/unix/meson.build              |  1 -
> > >  lib/eal/version.map                   |  3 ++
> > >  lib/eal/windows/rte_thread.c          | 17 ++++++++
> > >  6 files changed, 95 insertions(+), 32 deletions(-)
> > >  rename lib/eal/{unix => common}/rte_thread.c (66%)
> > >
> > > diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
> >
> > Hello,
> >
> > I see the following error on this patch:
> >
> > ninja: error: loading 'build.ninja': No such file or directory
> >
> > https://lab.dpdk.org/results/dashboard/patchsets/18090/
> >
> > Locally, the build succeedes.
> > How can I see more information about this build error?
>

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [dpdk-ci] [PATCH v12 01/10] eal: add basic threading functions
  2021-08-03 15:11                                     ` [dpdk-dev] [dpdk-ci] " Owen Hilyard
@ 2021-08-03 15:38                                       ` Dmitry Kozlyuk
  2021-08-03 15:57                                         ` Owen Hilyard
  0 siblings, 1 reply; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-08-03 15:38 UTC (permalink / raw)
  To: Owen Hilyard
  Cc: Narcisa Ana Maria Vasile, dev, Thomas Monjalon, Khoa To,
	navasile, Dmitry Malloy, Tyler Retzlaff, talshn, Omar Cardona,
	Richardson, Bruce, David Marchand, pallavi.kadam, ci

2021-08-03 11:11 (UTC-0400), Owen Hilyard:
> It seems like meson encountered an error when building
> 
> app/test/meson.build:472:11: ERROR: Index 1 out of bounds of array of size
> > 1.
> >
> > A full log can be found at
> > /home-local/jenkins-local/jenkins-agent/workspace/Apply-Custom-Patch-Set/dpdk/build/meson-logs/meson-log.txt
> > ninja: error: loading 'build.ninja': No such file or directory
> >  
> 
> I can also reproduce the issue building locally (Meson version: 0.58.1):

Meson 0.58+ has a known issue on Windows:
https://github.com/mesonbuild/meson/issues/8981
The last known good version is 0.57.2.

> 1. Get the DPDK main branch (f12b844b54f4ea7908ecb08ade04c7366ede031d)
> 2. apply all patches
> 3. meson $BUILD_DIR
> 
> Meson doesn't really give any extra information aside from that, but
> looking at the build file, it looks like one of the fast_tests has no
> arguments and at least one is expected.
> 
> On Mon, Aug 2, 2021 at 5:37 PM Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> wrote:
> 
> > + ci@dpdk.org
> >
> > 2021-08-02 14:08 (UTC-0700), Narcisa Ana Maria Vasile:  
> > > On Mon, Aug 02, 2021 at 10:32:17AM -0700, Narcisa Ana Maria Vasile wrote:  
> > > > From: Narcisa Vasile <navasile@microsoft.com>
> > > >
> > > > Use a portable, type-safe representation for the thread identifier.
> > > > Add functions for comparing thread ids and obtaining the thread id
> > > > for the current thread.
> > > >
> > > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > > > ---
> > > >  lib/eal/common/meson.build            |  1 +
> > > >  lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
> > > >  lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
> > > >  lib/eal/unix/meson.build              |  1 -
> > > >  lib/eal/version.map                   |  3 ++
> > > >  lib/eal/windows/rte_thread.c          | 17 ++++++++
> > > >  6 files changed, 95 insertions(+), 32 deletions(-)
> > > >  rename lib/eal/{unix => common}/rte_thread.c (66%)
> > > >
> > > > diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build  
> > >
> > > Hello,
> > >
> > > I see the following error on this patch:
> > >
> > > ninja: error: loading 'build.ninja': No such file or directory
> > >
> > > https://lab.dpdk.org/results/dashboard/patchsets/18090/
> > >
> > > Locally, the build succeedes.
> > > How can I see more information about this build error?  
> >  


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [dpdk-ci] [PATCH v12 01/10] eal: add basic threading functions
  2021-08-03 15:38                                       ` Dmitry Kozlyuk
@ 2021-08-03 15:57                                         ` Owen Hilyard
  0 siblings, 0 replies; 290+ messages in thread
From: Owen Hilyard @ 2021-08-03 15:57 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Narcisa Ana Maria Vasile, dev, Thomas Monjalon, Khoa To,
	navasile, Dmitry Malloy, Tyler Retzlaff, talshn, Omar Cardona,
	Richardson, Bruce, David Marchand, pallavi.kadam, ci

Our windows servers are both running 0.57.1, but all of the *nix hosts are
running 0.58.1. This issue also happens on 0.57.1 and 0.57.2, with the
exact same steps to reproduce.

On Tue, Aug 3, 2021 at 11:38 AM Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
wrote:

> 2021-08-03 11:11 (UTC-0400), Owen Hilyard:
> > It seems like meson encountered an error when building
> >
> > app/test/meson.build:472:11: ERROR: Index 1 out of bounds of array of
> size
> > > 1.
> > >
> > > A full log can be found at
> > >
> /home-local/jenkins-local/jenkins-agent/workspace/Apply-Custom-Patch-Set/dpdk/build/meson-logs/meson-log.txt
> > > ninja: error: loading 'build.ninja': No such file or directory
> > >
> >
> > I can also reproduce the issue building locally (Meson version: 0.58.1):
>
> Meson 0.58+ has a known issue on Windows:
> https://github.com/mesonbuild/meson/issues/8981
> The last known good version is 0.57.2.
>
> > 1. Get the DPDK main branch (f12b844b54f4ea7908ecb08ade04c7366ede031d)
> > 2. apply all patches
> > 3. meson $BUILD_DIR
> >
> > Meson doesn't really give any extra information aside from that, but
> > looking at the build file, it looks like one of the fast_tests has no
> > arguments and at least one is expected.
> >
> > On Mon, Aug 2, 2021 at 5:37 PM Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> > wrote:
> >
> > > + ci@dpdk.org
> > >
> > > 2021-08-02 14:08 (UTC-0700), Narcisa Ana Maria Vasile:
> > > > On Mon, Aug 02, 2021 at 10:32:17AM -0700, Narcisa Ana Maria Vasile
> wrote:
> > > > > From: Narcisa Vasile <navasile@microsoft.com>
> > > > >
> > > > > Use a portable, type-safe representation for the thread identifier.
> > > > > Add functions for comparing thread ids and obtaining the thread id
> > > > > for the current thread.
> > > > >
> > > > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > > > > ---
> > > > >  lib/eal/common/meson.build            |  1 +
> > > > >  lib/eal/{unix => common}/rte_thread.c | 57
> ++++++++++++++++-----------
> > > > >  lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
> > > > >  lib/eal/unix/meson.build              |  1 -
> > > > >  lib/eal/version.map                   |  3 ++
> > > > >  lib/eal/windows/rte_thread.c          | 17 ++++++++
> > > > >  6 files changed, 95 insertions(+), 32 deletions(-)
> > > > >  rename lib/eal/{unix => common}/rte_thread.c (66%)
> > > > >
> > > > > diff --git a/lib/eal/common/meson.build
> b/lib/eal/common/meson.build
> > > >
> > > > Hello,
> > > >
> > > > I see the following error on this patch:
> > > >
> > > > ninja: error: loading 'build.ninja': No such file or directory
> > > >
> > > > https://lab.dpdk.org/results/dashboard/patchsets/18090/
> > > >
> > > > Locally, the build succeedes.
> > > > How can I see more information about this build error?
> > >
>
>

^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading
  2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                 ` (9 preceding siblings ...)
  2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                               ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                   ` (10 more replies)
  10 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Add support for pthread_mutex_trylock
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v13:
 - Fix syntax error in unit tests

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c


Narcisa Vasile (10):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  eal: add EAL argument for setting thread priority
  Add unit tests for thread API

 app/test/meson.build                |   2 +
 app/test/test_threads.c             | 419 ++++++++++++++++++++
 lib/eal/common/eal_common_options.c |  28 +-
 lib/eal/common/eal_internal_cfg.h   |   2 +
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/common/meson.build          |   1 +
 lib/eal/common/rte_thread.c         | 445 +++++++++++++++++++++
 lib/eal/include/rte_thread.h        | 406 ++++++++++++++++++-
 lib/eal/unix/meson.build            |   1 -
 lib/eal/unix/rte_thread.c           |  92 -----
 lib/eal/version.map                 |  20 +
 lib/eal/windows/eal_lcore.c         | 176 ++++++---
 lib/eal/windows/eal_windows.h       |  10 +
 lib/eal/windows/include/sched.h     |   2 +-
 lib/eal/windows/rte_thread.c        | 588 ++++++++++++++++++++++++++--
 15 files changed, 2020 insertions(+), 174 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 01/10] eal: add basic threading functions
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
                                                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 887012d02a..ba7dcda664 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -426,6 +426,9 @@ EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 02/10] eal: add thread attributes
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 93 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 187 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..032ff73b36 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,30 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_UNDEFINED         = 0,
+	/**< priority hasn't been defined */
+	RTE_THREAD_PRIORITY_NORMAL            = 1,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 2,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +87,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ba7dcda664..9ffa5eb15e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 03/10] eal/windows: translate Windows errors to errno-style errors
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 032ff73b36..bf649c2fe6 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -235,9 +235,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 04/10] eal: implement functions for thread affinity management
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (2 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index bf649c2fe6..ca4ade60e2 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -87,6 +87,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 9ffa5eb15e..7ed4cd779e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -433,6 +433,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 7cc811485d..c1f8699777 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 05/10] eal: implement thread priority management functions
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (3 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 49 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 17 ++++++++++
 lib/eal/version.map          |  1 +
 lib/eal/windows/rte_thread.c | 66 ++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fcebf7097c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,55 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index ca4ade60e2..5514b2f57f 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -215,6 +215,23 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 7ed4cd779e..df01bbbbe4 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -435,6 +435,7 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..fb04718f58 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,72 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 06/10] eal: add thread lifetime management
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (4 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 107 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 138 ++++++++++++++++++++++++++++++++
 5 files changed, 304 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fcebf7097c..a0a51bc190 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -144,6 +144,113 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			/*
+			 * Set the inherit scheduler parameter to explicit,
+			 * otherwise the priority attribute is ignored.
+			 */
+			ret = pthread_attr_setinheritsched(attrp,
+					PTHREAD_EXPLICIT_SCHED);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+				goto cleanup;
+			}
+
+			ret = thread_map_priority_to_os_value(
+					thread_attr->priority,
+					&param.sched_priority, &policy
+					);
+			if (ret != 0)
+				goto cleanup;
+
+			ret = pthread_attr_setschedpolicy(attrp, policy);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+				goto cleanup;
+			}
+
+			ret = pthread_attr_setschedparam(attrp, &param);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+				goto cleanup;
+			}
+		}
+
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = pthread_attr_setaffinity_np(attrp,
+					sizeof(thread_attr->cpuset),
+					&thread_attr->cpuset);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5514b2f57f..098c3ba343 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -213,6 +214,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index df01bbbbe4..02994dd3fb 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -436,6 +436,9 @@ EXPERIMENTAL {
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index fb04718f58..e5e420fadd 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -309,6 +314,139 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	unsigned long *func_ret = NULL;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	func_ret = (unsigned long *)ctx.thread_func(ctx.routine_args);
+	return *func_ret;
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		if (thread_attr->priority != RTE_THREAD_PRIORITY_UNDEFINED) {
+			ret = rte_thread_set_priority(*thread_id,
+						      thread_attr->priority);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 07/10] eal: implement functions for mutex management
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (5 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 +++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 94 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 53 ++++++++++++++++++++
 4 files changed, 212 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index a0a51bc190..ebae4a8af1 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -251,6 +251,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 098c3ba343..7e813b573d 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -56,6 +56,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -268,6 +288,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -287,6 +329,58 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 02994dd3fb..a1c7a8e87d 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -439,6 +439,10 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index e5e420fadd..23f00cfba2 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -447,6 +447,59 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 08/10] eal: implement functions for thread barrier management
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (6 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
                                                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index ebae4a8af1..3fdb267337 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -312,6 +312,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7e813b573d..40da83467b 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -76,6 +76,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -381,6 +393,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a1c7a8e87d..c081fdd96c 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -443,6 +443,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_lock;
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 23f00cfba2..b2ff16f51f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -500,6 +500,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (7 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-15 19:56                                   ` Dmitry Kozlyuk
  2021-08-18 21:28                                   ` Stephen Hemminger
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 2 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Allow the user to choose the thread priority through an EAL
command line argument.

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

 Example:
./dpdk-l2fwd -l 0-3 -n 4 --thread-prio normal -- -q 8 -p ffff

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
 lib/eal/common/eal_internal_cfg.h   |  2 ++
 lib/eal/common/eal_options.h        |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ff5861b5f3..9d29696b84 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -107,6 +107,7 @@ eal_long_options[] = {
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
 
 	/* legacy options that will be removed in future */
 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
@@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
 	return 0;
 }
 
+static int
+eal_parse_thread_priority(const char *arg)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	enum rte_thread_priority priority;
+
+	if (!strncmp("normal", arg, sizeof("normal")))
+		priority = RTE_THREAD_PRIORITY_NORMAL;
+	else if (!strncmp("realtime", arg, sizeof("realtime")))
+		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+	else
+		return -1;
+
+	internal_conf->thread_priority = priority;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-
+	case OPT_THREAD_PRIORITY_NUM:
+		if (eal_parse_thread_priority(optarg) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_THREAD_PRIORITY "\n");
+			return -1;
+		}
+		break;
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -2088,6 +2113,7 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
 #endif
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index d6c0470eb8..b2996cd65b 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -94,6 +94,8 @@ struct internal_config {
 	unsigned int no_telemetry; /**< true to disable Telemetry */
 	struct simd_bitwidth max_simd_bitwidth;
 	/**< max simd bitwidth path to use */
+	enum rte_thread_priority thread_priority;
+	/**< thread priority to configure */
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
index 7b348e707f..9f5b209f64 100644
--- a/lib/eal/common/eal_options.h
+++ b/lib/eal/common/eal_options.h
@@ -93,6 +93,8 @@ enum {
 	OPT_NO_TELEMETRY_NUM,
 #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
 	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_THREAD_PRIORITY          "thread-prio"
+	OPT_THREAD_PRIORITY_NUM,
 
 	/* legacy option that will be removed in future */
 #define OPT_PCI_BLACKLIST     "pci-blacklist"
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v13 10/10] Add unit tests for thread API
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (8 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-08-03 19:01                                 ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-03 19:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |   2 +
 app/test/test_threads.c | 419 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 421 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index a7611686ad..57e61ce601 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -140,6 +140,7 @@ test_sources = files(
         'test_table_tables.c',
         'test_tailq.c',
         'test_thash.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -276,6 +277,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest', true],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..beaa303506
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,419 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <pthread.h>
+
+#include <rte_thread.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+#define TEST_THREADS_LOG(func) \
+		printf("Error at line %d. %s failed!\n", __LINE__, func)
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			break;
+		}
+	}
+
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			return -1;
+		}
+
+		if (rte_thread_equal(threads_ids[j], self_ids[j]) == 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_context {
+	rte_thread_barrier *barrier;
+	size_t *thread_count;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+
+	struct thread_context *ctx = arg;
+
+	(void)__atomic_add_fetch(ctx->thread_count, 1, __ATOMIC_RELAXED);
+
+	if (rte_thread_barrier_wait(ctx->barrier) > 0)
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_context ctx[THREADS_COUNT] = {};
+	rte_thread_barrier barrier;
+	size_t count = 0;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_barrier_init(&barrier, THREADS_COUNT + 1);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].thread_count = &count;
+		ctx[i].barrier = &barrier;
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_barrier, &ctx[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+	ret = rte_thread_barrier_wait(ctx->barrier);
+	if (ret > 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+		ret = -1;
+		goto error;
+	}
+
+	if (count != i) {
+		ret = -1;
+		printf("Error, expected thread count(%zu) to be equal "
+			"to the number of threads that wait at the barrier(%zu)\n",
+			count, i);
+		goto error;
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_destroy()");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static size_t val;
+
+static void *
+thread_loop_mutex(void *arg)
+{
+	rte_thread_mutex *mutex = arg;
+
+	rte_thread_mutex_lock(mutex);
+	val++;
+	rte_thread_mutex_unlock(mutex);
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_mutex mutex;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	/*
+	 * The value that each thread will increment while holding the mutex.
+	 */
+	val = 0;
+
+	ret = rte_thread_mutex_init(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_mutex, &mutex) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+		}
+	}
+
+	ret = rte_thread_mutex_destroy(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_destroy()");
+		ret = -1;
+	}
+
+	if (i != val) {
+		printf("Unexpected value: %zu!. Expected %zu. "
+			"Each thread should increment the value once.\n",
+			val, i);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_affinity_ctx {
+	size_t idx;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+			&cpuset) != 0) {
+		ctx->result = 1;
+		TEST_THREADS_LOG("pthread_getaffinity_np()");
+		return NULL;
+	}
+
+	if (!CPU_ISSET(ctx->idx, &cpuset)) {
+		ctx->result = 1;
+		printf("CPU %zu should be set for thread %zu\n",
+			ctx->idx, ctx->idx);
+		return NULL;
+	}
+
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (i != ctx->idx && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			printf("CPU %zu should not be set for thread %zu\n",
+				i, ctx->idx);
+			return NULL;
+		}
+	}
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		CPU_ZERO(&cpuset);
+		CPU_SET(i, &cpuset);
+
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("rte_thread_attr_set_affinity()");
+			goto error;
+		}
+
+		ctx[i].idx = i;
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity,
+				&ctx[i]) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+
+		if (ctx[j].result != 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	size_t j;
+	int ret = 0;
+	int policy;
+	struct sched_param param;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_set_priority()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		ret = pthread_getschedparam(
+				(pthread_t)threads_ids[i].opaque_id,
+				&policy, &param);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("pthread_getschedparam()");
+			goto error;
+		}
+
+		if (policy != SCHED_OTHER || param.sched_priority != 0) {
+			ret = -1;
+			printf("Unexpected priority: %d or policy: %d\n",
+					param.sched_priority, SCHED_OTHER);
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_detach(threads_ids[j]);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_detach()");
+			return -1;
+		}
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
@ 2021-08-15 19:56                                   ` Dmitry Kozlyuk
  2021-08-18 21:28                                   ` Stephen Hemminger
  1 sibling, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-08-15 19:56 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-08-03 12:01 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Allow the user to choose the thread priority through an EAL
> command line argument.

EAL options documentation update is needed.
With current wording the user may ask: the priority of which thread?

> The user can choose thread priority through an EAL parameter,
> when starting an application.  If EAL parameter is not used,
> the per-platform default value for thread priority is used.
> Otherwise administrator has an option to set one of available options:
>  --thread-prio normal
>  --thread-prio realtime
> 
>  Example:
> ./dpdk-l2fwd -l 0-3 -n 4 --thread-prio normal -- -q 8 -p ffff

IIUC, with this patch --thread-prio affects nothing,
because the value it fills is not used anywhere.
Why is it needed in this patchset then?

> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/eal/common/eal_common_options.c | 28 +++++++++++++++++++++++++++-
>  lib/eal/common/eal_internal_cfg.h   |  2 ++
>  lib/eal/common/eal_options.h        |  2 ++
>  3 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
> index ff5861b5f3..9d29696b84 100644
> --- a/lib/eal/common/eal_common_options.c
> +++ b/lib/eal/common/eal_common_options.c
> @@ -107,6 +107,7 @@ eal_long_options[] = {
>  	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
>  	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
>  	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
> +	{OPT_THREAD_PRIORITY,   1, NULL, OPT_THREAD_PRIORITY_NUM},
>  
>  	/* legacy options that will be removed in future */
>  	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
> @@ -1412,6 +1413,24 @@ eal_parse_simd_bitwidth(const char *arg)
>  	return 0;
>  }
>  
> +static int
> +eal_parse_thread_priority(const char *arg)
> +{
> +	struct internal_config *internal_conf =
> +		eal_get_internal_configuration();
> +	enum rte_thread_priority priority;
> +
> +	if (!strncmp("normal", arg, sizeof("normal")))
> +		priority = RTE_THREAD_PRIORITY_NORMAL;
> +	else if (!strncmp("realtime", arg, sizeof("realtime")))
> +		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
> +	else
> +		return -1;

Why not just `strcmp()`?

> +
> +	internal_conf->thread_priority = priority;
> +	return 0;
> +}
> +
>  static int
>  eal_parse_base_virtaddr(const char *arg)
>  {
> @@ -1825,7 +1844,13 @@ eal_parse_common_option(int opt, const char *optarg,
>  			return -1;
>  		}
>  		break;
> -
> +	case OPT_THREAD_PRIORITY_NUM:
> +		if (eal_parse_thread_priority(optarg) < 0) {
> +			RTE_LOG(ERR, EAL, "invalid parameter for --"
> +					OPT_THREAD_PRIORITY "\n");
> +			return -1;
> +		}
> +		break;
>  	/* don't know what to do, leave this to caller */
>  	default:
>  		return 1;
> @@ -2088,6 +2113,7 @@ eal_common_usage(void)
>  	       "                      (can be used multiple times)\n"
>  	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
>  	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
> +	       "  --"OPT_THREAD_PRIORITY"   Set threads priority (normal|realtime)\n"
>  #ifndef RTE_EXEC_ENV_WINDOWS
>  	       "  --"OPT_SYSLOG"            Set syslog facility\n"
>  #endif
> diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
> index d6c0470eb8..b2996cd65b 100644
> --- a/lib/eal/common/eal_internal_cfg.h
> +++ b/lib/eal/common/eal_internal_cfg.h
> @@ -94,6 +94,8 @@ struct internal_config {
>  	unsigned int no_telemetry; /**< true to disable Telemetry */
>  	struct simd_bitwidth max_simd_bitwidth;
>  	/**< max simd bitwidth path to use */
> +	enum rte_thread_priority thread_priority;
> +	/**< thread priority to configure */

Where is the default set?
If you remove RTE_THREAD_PRIORITY_UNDEFINED in patch 2/10,
it will be RTE_THREAD_PRIORITY_NORMAL in zeroed-out structure, which is OK.

>  };
>  
>  void eal_reset_internal_config(struct internal_config *internal_cfg);
> diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h
> index 7b348e707f..9f5b209f64 100644
> --- a/lib/eal/common/eal_options.h
> +++ b/lib/eal/common/eal_options.h
> @@ -93,6 +93,8 @@ enum {
>  	OPT_NO_TELEMETRY_NUM,
>  #define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
>  	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
> +#define OPT_THREAD_PRIORITY          "thread-prio"
> +	OPT_THREAD_PRIORITY_NUM,
>  
>  	/* legacy option that will be removed in future */
>  #define OPT_PCI_BLACKLIST     "pci-blacklist"


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
  2021-08-15 19:56                                   ` Dmitry Kozlyuk
@ 2021-08-18 21:28                                   ` Stephen Hemminger
  2021-08-19  9:06                                     ` Bruce Richardson
  1 sibling, 1 reply; 290+ messages in thread
From: Stephen Hemminger @ 2021-08-18 21:28 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Tue,  3 Aug 2021 12:01:30 -0700
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> +static int
> +eal_parse_thread_priority(const char *arg)
> +{
> +	struct internal_config *internal_conf =
> +		eal_get_internal_configuration();
> +	enum rte_thread_priority priority;
> +
> +	if (!strncmp("normal", arg, sizeof("normal")))
> +		priority = RTE_THREAD_PRIORITY_NORMAL;
> +	else if (!strncmp("realtime", arg, sizeof("realtime")))
> +		priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
> +	else
> +		return -1;
> +
> +	internal_conf->thread_priority = priority;
> +	return 0;
> +}
> +

In my experience using real time priority is dangerous and risks starvation
and deadlock. The problem is that DPDK applications are typically 100% CPU
poll mode with no system calls; but the kernel has a number of worker threads
that can be required on those CPUs.

The typical failure is a disk completion interrupt happens on a CPU that
is being used by DPDK lcore thread. With RT priority, the kernel thread to
process that I/O completion never runs because the RT user thread has
higher priority than the kernel I/O completion thread.

It maybe possible to workaround this with lots of hand crafting through
sysfs to reassign threads and irq's. Also, later kernels with full RT
might also help.

Before putting this in as part of DPDK in EAL, a full set of testing
and documentation of how to configure these kind of applications and
systems is needed.

I can't recommend this going in at this time.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority
  2021-08-18 21:28                                   ` Stephen Hemminger
@ 2021-08-19  9:06                                     ` Bruce Richardson
  2021-08-19 21:30                                       ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Bruce Richardson @ 2021-08-19  9:06 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Narcisa Ana Maria Vasile, dev, thomas, dmitry.kozliuk, khot,
	navasile, dmitrym, roretzla, talshn, ocardona, david.marchand,
	pallavi.kadam

On Wed, Aug 18, 2021 at 02:28:33PM -0700, Stephen Hemminger wrote:
> On Tue,  3 Aug 2021 12:01:30 -0700 Narcisa Ana Maria Vasile
> <navasile@linux.microsoft.com> wrote:
> 
> > +static int +eal_parse_thread_priority(const char *arg) +{ +
> > struct internal_config *internal_conf = +
> > eal_get_internal_configuration(); +	enum rte_thread_priority priority;
> > + +	if (!strncmp("normal", arg, sizeof("normal"))) +
> > priority = RTE_THREAD_PRIORITY_NORMAL; +	else if
> > (!strncmp("realtime", arg, sizeof("realtime"))) +		priority =
> > RTE_THREAD_PRIORITY_REALTIME_CRITICAL; +	else +		return -1;
> > + +	internal_conf->thread_priority = priority; +	return 0; +} +
> 
> In my experience using real time priority is dangerous and risks
> starvation and deadlock. The problem is that DPDK applications are
> typically 100% CPU poll mode with no system calls; but the kernel has a
> number of worker threads that can be required on those CPUs.
> 
> The typical failure is a disk completion interrupt happens on a CPU that
> is being used by DPDK lcore thread. With RT priority, the kernel thread
> to process that I/O completion never runs because the RT user thread has
> higher priority than the kernel I/O completion thread.
> 
> It maybe possible to workaround this with lots of hand crafting through
> sysfs to reassign threads and irq's. Also, later kernels with full RT
> might also help.
> 
> Before putting this in as part of DPDK in EAL, a full set of testing and
> documentation of how to configure these kind of applications and systems
> is needed.
>
I would tend to agree caution here, based on my experience of having locked
up a number of systems in the past when testing running DPDK apps with RT
priority!

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority
  2021-08-19  9:06                                     ` Bruce Richardson
@ 2021-08-19 21:30                                       ` Narcisa Ana Maria Vasile
  2021-08-19 21:33                                         ` Stephen Hemminger
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:30 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Stephen Hemminger, dev, thomas, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, talshn, ocardona, david.marchand,
	pallavi.kadam

On Thu, Aug 19, 2021 at 10:06:06AM +0100, Bruce Richardson wrote:
> On Wed, Aug 18, 2021 at 02:28:33PM -0700, Stephen Hemminger wrote:
> > On Tue,  3 Aug 2021 12:01:30 -0700 Narcisa Ana Maria Vasile
> > <navasile@linux.microsoft.com> wrote:
> > 
> > > +static int +eal_parse_thread_priority(const char *arg) +{ +
> > > struct internal_config *internal_conf = +
> > > eal_get_internal_configuration(); +	enum rte_thread_priority priority;
> > > + +	if (!strncmp("normal", arg, sizeof("normal"))) +
> > > priority = RTE_THREAD_PRIORITY_NORMAL; +	else if
> > > (!strncmp("realtime", arg, sizeof("realtime"))) +		priority =
> > > RTE_THREAD_PRIORITY_REALTIME_CRITICAL; +	else +		return -1;
> > > + +	internal_conf->thread_priority = priority; +	return 0; +} +
> > 
> > In my experience using real time priority is dangerous and risks
> > starvation and deadlock. The problem is that DPDK applications are
> > typically 100% CPU poll mode with no system calls; but the kernel has a
> > number of worker threads that can be required on those CPUs.
> > 
> > The typical failure is a disk completion interrupt happens on a CPU that
> > is being used by DPDK lcore thread. With RT priority, the kernel thread
> > to process that I/O completion never runs because the RT user thread has
> > higher priority than the kernel I/O completion thread.
> > 
> > It maybe possible to workaround this with lots of hand crafting through
> > sysfs to reassign threads and irq's. Also, later kernels with full RT
> > might also help.
> > 
> > Before putting this in as part of DPDK in EAL, a full set of testing and
> > documentation of how to configure these kind of applications and systems
> > is needed.
> >
> I would tend to agree caution here, based on my experience of having locked
> up a number of systems in the past when testing running DPDK apps with RT
> priority!

Thank you for the comments! I've added this option since it was requested by
multiple users. I understand RT priority causes issues on Linux platforms.
On Windows we want to be able to use REALTIME priority in certain scenarios.

Would it be acceptable to replace this option with a "HIGH_PRIORITY" one
and keep it realtime on Windows and choose a higher (but non-realtime) option on Linux?
However, there are 2 issues here:
 * We will have different behaviors between the 2 platforms.
 * Not sure if I can set a normal but higher priority on Linux. SCHED_OTHER only allows
   one value and Linux "nice" values don't help. If anyone knows of a way to accomplish
   this on Linux, please do advise.
Alternatively, we can have this option for Windows only.

In the meantime, I've removed this patch from this patchset in v14 as the cmdline option is not
being enabled yet, as DmitryK noted.



^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading
  2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                   ` (9 preceding siblings ...)
  2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                 ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                     ` (9 more replies)
  10 siblings, 10 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Add support for pthread_mutex_trylock
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v14:
- Remove patch "eal: add EAL argument for setting thread priority"
  This will be added later when enabling the new threading API.
- Remove priority enum value "_UNDEFINED". NORMAL is used
  as the default.
- Fix issue with thread return value.

v13:
 - Fix syntax error in unit tests

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (9):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  Add unit tests for thread API

 app/test/meson.build            |   2 +
 app/test/test_threads.c         | 419 +++++++++++++++++++++++
 lib/eal/common/meson.build      |   1 +
 lib/eal/common/rte_thread.c     | 441 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    | 404 +++++++++++++++++++++-
 lib/eal/unix/meson.build        |   1 -
 lib/eal/unix/rte_thread.c       |  92 -----
 lib/eal/version.map             |  20 ++
 lib/eal/windows/eal_lcore.c     | 176 +++++++---
 lib/eal/windows/eal_windows.h   |  10 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 584 ++++++++++++++++++++++++++++++--
 12 files changed, 1979 insertions(+), 173 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 1/9] eal: add basic threading functions
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
                                                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index edfca77779..eda250247b 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -80,6 +80,7 @@ sources += files(
         'rte_random.c',
         'rte_reciprocal.c',
         'rte_service.c',
+        'rte_thread.c',
         'rte_version.c',
 )
 
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index beeb986adc..8b8ba31518 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -426,6 +426,9 @@ EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 2/9] eal: add thread attributes
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 91 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..4ac36957ce 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,28 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = 0,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +85,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 8b8ba31518..b487ab5975 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 4ac36957ce..8a20215a94 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -233,9 +233,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 4/9] eal: implement functions for thread affinity management
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (2 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8a20215a94..5b100cafda 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -85,6 +85,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index b487ab5975..faf0361d37 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -433,6 +433,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 23ead6d30c..355ef181a5 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 5/9] eal: implement thread priority management functions
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (3 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function for setting the priority for a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 49 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 17 ++++++++++
 lib/eal/version.map          |  1 +
 lib/eal/windows/rte_thread.c | 66 ++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fcebf7097c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,55 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5b100cafda..a9cb6ec81c 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -213,6 +213,23 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index faf0361d37..790b5112fb 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -435,6 +435,7 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..fb04718f58 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,72 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 6/9] eal: add thread lifetime management
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (4 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 103 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 134 ++++++++++++++++++++++++++++++++
 5 files changed, 296 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fcebf7097c..39bb35ae23 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -144,6 +144,109 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+				PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		ret = thread_map_priority_to_os_value(thread_attr->priority,
+				&param.sched_priority, &policy);
+		if (ret != 0)
+			goto cleanup;
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = pthread_attr_setaffinity_np(attrp,
+					sizeof(thread_attr->cpuset),
+					&thread_attr->cpuset);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "pthread_attr_setaffinity_np failed\n");
+				goto cleanup;
+			}
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (value_ptr != NULL && *pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index a9cb6ec81c..8f36cf06e0 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -211,6 +212,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 790b5112fb..5e93420b8f 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -436,6 +436,9 @@ EXPERIMENTAL {
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index fb04718f58..5e368d6966 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -309,6 +314,135 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	return (DWORD)(uintptr_t)ctx.thread_func(ctx.routine_args);
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id,
+				thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 7/9] eal: implement functions for mutex management
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (5 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 +++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 94 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 53 ++++++++++++++++++++
 4 files changed, 212 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 39bb35ae23..05c235c215 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -247,6 +247,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8f36cf06e0..8015a984b8 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -266,6 +286,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -285,6 +327,58 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 5e93420b8f..fe6e4553de 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -439,6 +439,10 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5e368d6966..a1c8f123a3 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -443,6 +443,59 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 8/9] eal: implement functions for thread barrier management
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (6 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 05c235c215..ad27ff7d86 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -308,6 +308,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8015a984b8..b2aec28329 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -74,6 +74,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -379,6 +391,52 @@ int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index fe6e4553de..541dc13053 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -443,6 +443,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_lock;
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index a1c8f123a3..a0b2e0431f 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -496,6 +496,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (7 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-08-19 21:31                                   ` Narcisa Ana Maria Vasile
  2021-08-20 16:10                                     ` Narcisa Ana Maria Vasile
  2021-08-23 20:25                                     ` Dmitry Kozlyuk
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  9 siblings, 2 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-19 21:31 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |   2 +
 app/test/test_threads.c | 419 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 421 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index a7611686ad..57e61ce601 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -140,6 +140,7 @@ test_sources = files(
         'test_table_tables.c',
         'test_tailq.c',
         'test_thash.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -276,6 +277,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest', true],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..beaa303506
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,419 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <pthread.h>
+
+#include <rte_thread.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+#define TEST_THREADS_LOG(func) \
+		printf("Error at line %d. %s failed!\n", __LINE__, func)
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			break;
+		}
+	}
+
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			return -1;
+		}
+
+		if (rte_thread_equal(threads_ids[j], self_ids[j]) == 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_context {
+	rte_thread_barrier *barrier;
+	size_t *thread_count;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+
+	struct thread_context *ctx = arg;
+
+	(void)__atomic_add_fetch(ctx->thread_count, 1, __ATOMIC_RELAXED);
+
+	if (rte_thread_barrier_wait(ctx->barrier) > 0)
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_context ctx[THREADS_COUNT] = {};
+	rte_thread_barrier barrier;
+	size_t count = 0;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_barrier_init(&barrier, THREADS_COUNT + 1);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].thread_count = &count;
+		ctx[i].barrier = &barrier;
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_barrier, &ctx[i]) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+	ret = rte_thread_barrier_wait(ctx->barrier);
+	if (ret > 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_wait()");
+		ret = -1;
+		goto error;
+	}
+
+	if (count != i) {
+		ret = -1;
+		printf("Error, expected thread count(%zu) to be equal "
+			"to the number of threads that wait at the barrier(%zu)\n",
+			count, i);
+		goto error;
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_barrier_destroy()");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static size_t val;
+
+static void *
+thread_loop_mutex(void *arg)
+{
+	rte_thread_mutex *mutex = arg;
+
+	rte_thread_mutex_lock(mutex);
+	val++;
+	rte_thread_mutex_unlock(mutex);
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_mutex mutex;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	/*
+	 * The value that each thread will increment while holding the mutex.
+	 */
+	val = 0;
+
+	ret = rte_thread_mutex_init(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_mutex, &mutex) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+		}
+	}
+
+	ret = rte_thread_mutex_destroy(&mutex);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_mutex_destroy()");
+		ret = -1;
+	}
+
+	if (i != val) {
+		printf("Unexpected value: %zu!. Expected %zu. "
+			"Each thread should increment the value once.\n",
+			val, i);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+struct thread_affinity_ctx {
+	size_t idx;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+			&cpuset) != 0) {
+		ctx->result = 1;
+		TEST_THREADS_LOG("pthread_getaffinity_np()");
+		return NULL;
+	}
+
+	if (!CPU_ISSET(ctx->idx, &cpuset)) {
+		ctx->result = 1;
+		printf("CPU %zu should be set for thread %zu\n",
+			ctx->idx, ctx->idx);
+		return NULL;
+	}
+
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (i != ctx->idx && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			printf("CPU %zu should not be set for thread %zu\n",
+				i, ctx->idx);
+			return NULL;
+		}
+	}
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		CPU_ZERO(&cpuset);
+		CPU_SET(i, &cpuset);
+
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("rte_thread_attr_set_affinity()");
+			goto error;
+		}
+
+		ctx[i].idx = i;
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity,
+				&ctx[i]) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+
+		if (ctx[j].result != 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	size_t j;
+	int ret = 0;
+	int policy;
+	struct sched_param param;
+
+	ret = rte_thread_attr_init(&attr);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_init()");
+		return -1;
+	}
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	if (ret != 0) {
+		TEST_THREADS_LOG("rte_thread_attr_set_priority()");
+		return -1;
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, created only %zu threads\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		ret = pthread_getschedparam(
+				(pthread_t)threads_ids[i].opaque_id,
+				&policy, &param);
+		if (ret != 0) {
+			ret = -1;
+			TEST_THREADS_LOG("pthread_getschedparam()");
+			goto error;
+		}
+
+		if (policy != SCHED_OTHER || param.sched_priority != 0) {
+			ret = -1;
+			printf("Unexpected priority: %d or policy: %d\n",
+					param.sched_priority, SCHED_OTHER);
+			goto error;
+		}
+
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_join(threads_ids[j], NULL);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_join()");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	size_t j;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		if (rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL) != 0) {
+			printf("Error, Only %zu threads created.\n", i);
+			goto error;
+		}
+	}
+
+error:
+	for (j = 0; j < i; ++j) {
+		ret = rte_thread_detach(threads_ids[j]);
+		if (ret != 0) {
+			TEST_THREADS_LOG("rte_thread_detach()");
+			return -1;
+		}
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority
  2021-08-19 21:30                                       ` Narcisa Ana Maria Vasile
@ 2021-08-19 21:33                                         ` Stephen Hemminger
  0 siblings, 0 replies; 290+ messages in thread
From: Stephen Hemminger @ 2021-08-19 21:33 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: Bruce Richardson, dev, thomas, dmitry.kozliuk, khot, navasile,
	dmitrym, roretzla, talshn, ocardona, david.marchand,
	pallavi.kadam

On Thu, 19 Aug 2021 14:30:19 -0700
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> On Thu, Aug 19, 2021 at 10:06:06AM +0100, Bruce Richardson wrote:
> > On Wed, Aug 18, 2021 at 02:28:33PM -0700, Stephen Hemminger wrote:  
> > > On Tue,  3 Aug 2021 12:01:30 -0700 Narcisa Ana Maria Vasile
> > > <navasile@linux.microsoft.com> wrote:
> > >   
> > > > +static int +eal_parse_thread_priority(const char *arg) +{ +
> > > > struct internal_config *internal_conf = +
> > > > eal_get_internal_configuration(); +	enum rte_thread_priority priority;
> > > > + +	if (!strncmp("normal", arg, sizeof("normal"))) +
> > > > priority = RTE_THREAD_PRIORITY_NORMAL; +	else if
> > > > (!strncmp("realtime", arg, sizeof("realtime"))) +		priority =
> > > > RTE_THREAD_PRIORITY_REALTIME_CRITICAL; +	else +		return -1;
> > > > + +	internal_conf->thread_priority = priority; +	return 0; +} +  
> > > 
> > > In my experience using real time priority is dangerous and risks
> > > starvation and deadlock. The problem is that DPDK applications are
> > > typically 100% CPU poll mode with no system calls; but the kernel has a
> > > number of worker threads that can be required on those CPUs.
> > > 
> > > The typical failure is a disk completion interrupt happens on a CPU that
> > > is being used by DPDK lcore thread. With RT priority, the kernel thread
> > > to process that I/O completion never runs because the RT user thread has
> > > higher priority than the kernel I/O completion thread.
> > > 
> > > It maybe possible to workaround this with lots of hand crafting through
> > > sysfs to reassign threads and irq's. Also, later kernels with full RT
> > > might also help.
> > > 
> > > Before putting this in as part of DPDK in EAL, a full set of testing and
> > > documentation of how to configure these kind of applications and systems
> > > is needed.
> > >  
> > I would tend to agree caution here, based on my experience of having locked
> > up a number of systems in the past when testing running DPDK apps with RT
> > priority!  
> 
> Thank you for the comments! I've added this option since it was requested by
> multiple users. I understand RT priority causes issues on Linux platforms.
> On Windows we want to be able to use REALTIME priority in certain scenarios.
> 
> Would it be acceptable to replace this option with a "HIGH_PRIORITY" one
> and keep it realtime on Windows and choose a higher (but non-realtime) option on Linux?
> However, there are 2 issues here:
>  * We will have different behaviors between the 2 platforms.
>  * Not sure if I can set a normal but higher priority on Linux. SCHED_OTHER only allows
>    one value and Linux "nice" values don't help. If anyone knows of a way to accomplish
>    this on Linux, please do advise.
> Alternatively, we can have this option for Windows only.
> 
> In the meantime, I've removed this patch from this patchset in v14 as the cmdline option is not
> being enabled yet, as DmitryK noted.
> 
> 

I think on Linux it should produce a big a*** warning message.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-08-20 16:10                                     ` Narcisa Ana Maria Vasile
  2021-08-20 16:54                                       ` Dmitry Kozlyuk
  2021-08-23 20:25                                     ` Dmitry Kozlyuk
  1 sibling, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-08-20 16:10 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

On Thu, Aug 19, 2021 at 02:31:34PM -0700, Narcisa Ana Maria Vasile wrote:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> As a new API for threading is introduced,
> a set of unit tests have been added to test the new interface.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  app/test/meson.build    |   2 +
>  app/test/test_threads.c | 419 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 421 insertions(+)
>  create mode 100644 app/test/test_threads.c
> 

There's a failure here on Alpine Linux:
"error: implicit declaration of function 'pthread_attr_setaffinity_np';
did you mean 'pthread_setaffinity_np'? [-Werror=implicit-function-declaration]"

It looks like "pthread_attr_setaffinity_np" is not available on Alpine Linux. However,
other affinity functions such as "pthread_setaffinity_np" are present. Is there a guard that
I can use here to check if the pthread_*_np functions are available, similar to RTE_HAS_CPUSET for cpuset?


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API
  2021-08-20 16:10                                     ` Narcisa Ana Maria Vasile
@ 2021-08-20 16:54                                       ` Dmitry Kozlyuk
  0 siblings, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-08-20 16:54 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-08-20 09:10 (UTC-0700), Narcisa Ana Maria Vasile:
> On Thu, Aug 19, 2021 at 02:31:34PM -0700, Narcisa Ana Maria Vasile wrote:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > As a new API for threading is introduced,
> > a set of unit tests have been added to test the new interface.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
> >  app/test/meson.build    |   2 +
> >  app/test/test_threads.c | 419 ++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 421 insertions(+)
> >  create mode 100644 app/test/test_threads.c
> >   
> 
> There's a failure here on Alpine Linux:
> "error: implicit declaration of function 'pthread_attr_setaffinity_np';
> did you mean 'pthread_setaffinity_np'? [-Werror=implicit-function-declaration]"
> 
> It looks like "pthread_attr_setaffinity_np" is not available on Alpine Linux. However,
> other affinity functions such as "pthread_setaffinity_np" are present. Is there a guard that
> I can use here to check if the pthread_*_np functions are available, similar to RTE_HAS_CPUSET for cpuset?

Even if there is one, you still need to handle the Alpine case.
41b5a7a8494e ("vdpa/mlx5: replace pthread functions unavailable in musl")
is an example how to solve this particular case.
It's also what that rte_ctrl_thread_create() does.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
  2021-08-20 16:10                                     ` Narcisa Ana Maria Vasile
@ 2021-08-23 20:25                                     ` Dmitry Kozlyuk
  1 sibling, 0 replies; 290+ messages in thread
From: Dmitry Kozlyuk @ 2021-08-23 20:25 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, thomas, khot, navasile, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

2021-08-19 14:31 (UTC-0700), Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> As a new API for threading is introduced,
> a set of unit tests have been added to test the new interface.

There are three substantial issues with this tests:

1. They use pthread API to verify the results, but the whole point of
introducing this new API is to abstract pthread or Win32 interfaces
and eventually to remove pthread shim from Windows EAL. Furthermore, new new
API actually has functions to do the checks, e.g. rte_thread_get_affinity().

2. They don't really check the contracts:

2.1. Mutex test could pass even if it used no locking at all.
2.2. Barrier test does not verify that threads are blocked/unblocked.
2.3. No test for static initialization.

See also comments inline.

[...]
> +#define TEST_THREADS_LOG(func) \
> +		printf("Error at line %d. %s failed!\n", __LINE__, func)

rte_test.h contains some useful macros like this one.

[...]
> +static int
> +test_thread_self(void)
> +{
> +	rte_thread_t threads_ids[THREADS_COUNT];
> +	rte_thread_t self_ids[THREADS_COUNT] = {};
> +	size_t i;
> +	size_t j;
> +	int ret = 0;
> +
> +	for (i = 0; i < THREADS_COUNT; ++i) {
> +		if (rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
> +				&self_ids[i]) != 0) {
> +			printf("Error, Only %zu threads created.\n", i);

Typo: "only" (in other copies too).
This test could use RTE_LOG_REGISTER() and log levels if needed.

> +			break;
> +		}
> +	}
> +
> +	for (j = 0; j < i; ++j) {
> +		ret = rte_thread_join(threads_ids[j], NULL);
> +		if (ret != 0) {
> +			TEST_THREADS_LOG("rte_thread_join()");
> +			return -1;
> +		}
> +
> +		if (rte_thread_equal(threads_ids[j], self_ids[j]) == 0)
> +			ret = -1;

Tests should indicate what exactly went wrong.
Suggesting RTE_TEST_ASSERT_EQUAL() here.

> +	}
> +
> +	return ret;
> +}
> +
> +struct thread_context {
> +	rte_thread_barrier *barrier;
> +	size_t *thread_count;
> +};
> +
> +static void *
> +thread_loop_barrier(void *arg)
> +{
> +

Unnecessary empty line.

> +	struct thread_context *ctx = arg;
> +
> +	(void)__atomic_add_fetch(ctx->thread_count, 1, __ATOMIC_RELAXED);
> +
> +	if (rte_thread_barrier_wait(ctx->barrier) > 0)
> +		TEST_THREADS_LOG("rte_thread_barrier_wait()");
> +
> +	return NULL;
> +}
[...]


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading
  2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                     ` (8 preceding siblings ...)
  2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                   ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                       ` (9 more replies)
  9 siblings, 10 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_get_priority      - retrieves the priority of a thread
                               from the OS
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v15:
- Add try_lock mutex functionality. If the mutex is already owned by a
  different thread, the function returns immediately. Otherwise, 
  the mutex will be acquired.
- Add function for getting the priority of a thread.
  An auxiliary function that translates the OS priority to the
  EAL accepted ones is added.
- Fix unit tests logging, add descriptive asserts that mark test failures.
  Verify mutex locking, verify barrier return values. Add test for
  statically initialized mutexes.
- Fix Alpine build by removing the use of pthread_attr_set_affinity() and
  using pthread_set_affinity() after the thread is created.

v14:
- Remove patch "eal: add EAL argument for setting thread priority"
  This will be added later when enabling the new threading API.
- Remove priority enum value "_UNDEFINED". NORMAL is used
  as the default.
- Fix issue with thread return value.

v13:
 - Fix syntax error in unit tests

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (9):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  Add unit tests for thread API

 app/test/meson.build            |   2 +
 app/test/test_threads.c         | 359 +++++++++++++++++
 lib/eal/common/meson.build      |   1 +
 lib/eal/common/rte_thread.c     | 496 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    | 435 ++++++++++++++++++++-
 lib/eal/unix/meson.build        |   1 -
 lib/eal/unix/rte_thread.c       |  92 -----
 lib/eal/version.map             |  22 ++
 lib/eal/windows/eal_lcore.c     | 176 ++++++---
 lib/eal/windows/eal_windows.h   |  10 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 656 ++++++++++++++++++++++++++++++--
 12 files changed, 2079 insertions(+), 173 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 1/9] eal: add basic threading functions
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
                                                       ` (8 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index 6d01b0f072..5299bb80d3 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -51,5 +51,6 @@ if not is_windows
             'hotplug_mp.c',
             'malloc_mp.c',
             'rte_keepalive.c',
+            'rte_thread.c'
     )
 endif
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 38f7de83e1..d1c313d519 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -420,6 +420,9 @@ EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 2/9] eal: add thread attributes
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                       ` (7 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 91 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..4ac36957ce 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,28 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = 0,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +85,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index d1c313d519..a1b944788e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                       ` (6 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 4ac36957ce..8a20215a94 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -233,9 +233,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 4/9] eal: implement functions for thread affinity management
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (2 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                       ` (5 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8a20215a94..5b100cafda 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -85,6 +85,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a1b944788e..58b9553d59 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -427,6 +427,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 23ead6d30c..355ef181a5 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 5/9] eal: implement thread priority management functions
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (3 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                       ` (4 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for setting and getting the priority of a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  96 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  34 ++++++++++
 lib/eal/version.map          |   2 +
 lib/eal/windows/rte_thread.c | 127 +++++++++++++++++++++++++++++++++++
 4 files changed, 259 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fb1199adfe 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,102 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_priority(int policy, int os_pri,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (policy) {
+	case SCHED_OTHER:
+		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case SCHED_RR:
+		if (os_pri == sched_get_priority_max(SCHED_RR)) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = pthread_getschedparam(thread_id.opaque_id, &policy, &param);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
+		goto cleanup;
+	}
+
+	return thread_map_os_priority_to_eal_priority(policy,
+			param.sched_priority, priority);
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5b100cafda..7077c9ce46 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -213,6 +213,40 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Get the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get priority.
+ *
+ * @param priority
+ *   Location to store the retrieved priority.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority);
+
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 58b9553d59..dcc2c479e9 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,8 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_get_priority;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..5c02a6eaff 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,133 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_value(int os_pri, int pri_class,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (pri_class) {
+	case NORMAL_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_NORMAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case REALTIME_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	HANDLE thread_handle = NULL;
+	DWORD pri_class;
+	int os_pri;
+	int ret;
+
+	pri_class = GetPriorityClass(GetCurrentProcess());
+	if (pri_class == 0) {
+		ret = thread_log_last_error("GetPriorityClass()");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+			THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	os_pri = GetThreadPriority(thread_handle);
+	if (os_pri == THREAD_PRIORITY_ERROR_RETURN) {
+		ret = thread_log_last_error("GetThreadPriority()");
+		goto cleanup;
+	}
+
+	ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);
+	if (ret != 0)
+		goto cleanup;
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 6/9] eal: add thread lifetime management
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (4 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                                       ` (3 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 103 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 134 ++++++++++++++++++++++++++++++++
 5 files changed, 296 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fb1199adfe..8787ecbb14 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -191,6 +191,109 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+				PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		ret = thread_map_priority_to_os_value(thread_attr->priority,
+				&param.sched_priority, &policy);
+		if (ret != 0)
+			goto cleanup;
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL && CPU_COUNT(&thread_attr->cpuset) > 0) {
+		ret = pthread_setaffinity_np(thread_id->opaque_id,
+				sizeof(thread_attr->cpuset),
+				&thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (value_ptr != NULL && *pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7077c9ce46..e841321819 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -211,6 +212,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index dcc2c479e9..ceaaf6b571 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -431,6 +431,9 @@ EXPERIMENTAL {
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5c02a6eaff..669a68d6a8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -370,6 +375,135 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	return (DWORD)(uintptr_t)ctx.thread_func(ctx.routine_args);
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id,
+				thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 7/9] eal: implement functions for mutex management
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (5 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                                       ` (2 subsequent siblings)
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock, trylock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  69 ++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 108 +++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |   5 ++
 lib/eal/windows/rte_thread.c |  64 +++++++++++++++++++++
 4 files changed, 246 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 8787ecbb14..a6f928d86c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -294,6 +294,75 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_trylock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index e841321819..b5782d396f 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -266,6 +286,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -302,6 +344,72 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Tries to lock a mutex.If the mutex is already held by a different thread,
+ * the function returns without blocking.
+ *
+ * @param mutex
+ *    The mutex that will be acquired, if not already locked.
+ *
+ * @return
+ *   On success, if the mutex is acquired, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_try_lock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ceaaf6b571..2506eb1587 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -434,6 +434,11 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_try_lock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 669a68d6a8..188e25e02e 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -504,6 +504,70 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (TryEnterCriticalSection(mutex->mutex_id) != 0)
+		return 0;
+
+	return EBUSY;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 8/9] eal: implement functions for thread barrier management
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (6 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index a6f928d86c..365b682aa4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -363,6 +363,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index b5782d396f..0adc854225 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -74,6 +74,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -410,6 +422,52 @@ int rte_thread_mutex_try_lock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 2506eb1587..ca05ba4f43 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -439,6 +439,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_try_lock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 188e25e02e..11b4863fe8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -568,6 +568,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v15 9/9] Add unit tests for thread API
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (7 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-10-08 22:40                                     ` Narcisa Ana Maria Vasile
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  9 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-08 22:40 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.
The tests verify that:
 * mutexes and barriers behave as expected
 * thread properties are applied correctly
 * the thread id is retrieved correctly
 * thread creation/destruction works properly

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |   2 +
 app/test/test_threads.c | 359 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 361 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f144d8b8ed..019c7e27d0 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -141,6 +141,7 @@ test_sources = files(
         'test_table_tables.c',
         'test_tailq.c',
         'test_thash.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -277,6 +278,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest', true],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..722d2689a8
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,359 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <rte_thread.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO);
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	int ret;
+	int i;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		RTE_TEST_ASSERT(rte_thread_join(threads_ids[i], NULL) == 0, "Failed to join thread!");
+		RTE_TEST_ASSERT_EQUAL(threads_ids[i].opaque_id,
+				self_ids[i].opaque_id, "Unexpected thread id!");
+	}
+
+	return 0;
+}
+
+struct thread_context {
+	rte_thread_barrier *barrier;
+	int barrier_result;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+	struct thread_context *ctx = arg;
+
+	ctx->barrier_result = rte_thread_barrier_wait(ctx->barrier);
+	if (ctx->barrier_result > 0)
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to wait at barrier!");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t thread_id;
+	struct thread_context ctx;
+	rte_thread_barrier barrier;
+	int ret = 0;
+	int result = 0;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	ctx.barrier = &barrier;
+	ret = rte_thread_create(&thread_id, NULL, thread_loop_barrier, &ctx);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	result = rte_thread_barrier_wait(&barrier);
+	RTE_TEST_ASSERT(result <= 0, "Failed to wait at the barrier!");
+
+	ret = rte_thread_join(thread_id, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	RTE_TEST_ASSERT(ctx.barrier_result <= 0, "Child thread failed to wait at the barrier!");
+	RTE_TEST_ASSERT_NOT_EQUAL(ctx.barrier_result, result, "Threads were not blocked at the barrier!");
+
+	return 0;
+}
+
+RTE_STATIC_MUTEX(static_mutex);
+
+struct mutex_loop_args {
+	rte_thread_barrier *barrier;
+	rte_thread_mutex *mutex;
+	unsigned long result_A;
+	unsigned long result_B;
+};
+
+static void *
+thread_loop_mutex_B(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) == 0) {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_B = 1;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_B = 2;
+	}
+
+	return NULL;
+}
+
+static void *
+thread_loop_mutex_A(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) != 0) {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_A = 2;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_A = 1;
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(rte_thread_mutex *pmutex)
+{
+	rte_thread_t thread_A;
+	rte_thread_t thread_B;
+	rte_thread_mutex mutex;
+	rte_thread_barrier barrier;
+	struct mutex_loop_args args;
+	int ret = 0;
+
+	/* If mutex is not statically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_init(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to initialize mutex!");
+	} else
+		mutex = *pmutex;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	args.mutex = &mutex;
+	args.barrier = &barrier;
+
+	ret = rte_thread_create(&thread_A, NULL, thread_loop_mutex_A, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_create(&thread_B, NULL, thread_loop_mutex_B, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_join(thread_A, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	ret = rte_thread_join(thread_B, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	RTE_TEST_ASSERT(args.result_A != args.result_B, "Mutex failed to be acquired or was acquired by both threads!");
+
+	/* Destroy if dynamically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_destroy(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to destroy mutex!");
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	return ret;
+}
+
+static int
+test_thread_mutex_static(void)
+{
+	return test_thread_mutex(&static_mutex);
+}
+
+static int
+test_thread_mutex_dynamic(void)
+{
+	return test_thread_mutex(NULL);
+}
+
+struct thread_affinity_ctx {
+	size_t idx;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0) {
+		ctx->result = 1;
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to get thread affinity!");
+		return NULL;
+	}
+
+	if (!CPU_ISSET(ctx->idx, &cpuset)) {
+		ctx->result = 1;
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "CPU %zu should be set for thread %zu\n",
+				ctx->idx, ctx->idx);
+		return NULL;
+	}
+
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (i != ctx->idx && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			rte_log(RTE_LOG_DEBUG, threads_logtype_test, "CPU %zu should not be set for thread %zu\n",
+					i, ctx->idx);
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize thread attributes!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		CPU_ZERO(&cpuset);
+		CPU_SET(i, &cpuset);
+
+		ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+		RTE_TEST_ASSERT(ret == 0, "Failed to set thread attributes!");
+
+		ctx[i].idx = i;
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity, &ctx[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(ctx[i].result, 0, "Unexpected thread affinity!");
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	int ret = 0;
+	enum rte_thread_priority priority;
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize  thread attributes!");
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread priority!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_return, NULL);
+			RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+
+		ret = rte_thread_get_priority(threads_ids[i], &priority);
+		RTE_TEST_ASSERT(ret == 0, "Failed to get thread priority!");
+
+		RTE_TEST_ASSERT_EQUAL(priority, RTE_THREAD_PRIORITY_NORMAL, "Unexpected thread priority!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+	}
+
+	return ret;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_detach(threads_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to detach thread!");
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex_static),
+			TEST_CASE(test_thread_mutex_dynamic),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading
  2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                       ` (8 preceding siblings ...)
  2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                     ` Narcisa Ana Maria Vasile
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                         ` (10 more replies)
  9 siblings, 11 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Given that the thread characteristics that are of interest
for DPDK applications are affinity and priority, the following structure
that represents thread attributes has been defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_get_priority      - retrieves the priority of a thread
                               from the OS
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

The user can choose thread priority through an EAL parameter,
when starting an application.  If EAL parameter is not used,
the per-platform default value for thread priority is used.
Otherwise administrator has an option to set one of available options:
 --thread-prio normal
 --thread-prio realtime

Example:
./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
A translation function that maps Windows error codes to errno-style
error codes is provided. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v16:
- Fix warning on freebsd by adding cast
- Change affinity unit test to consider ases when the requested CPU
  are not available on the system.
- Fix priority unit test to avoid termination of thread before the
  priority is checked.

v15:
- Add try_lock mutex functionality. If the mutex is already owned by a
  different thread, the function returns immediately. Otherwise, 
  the mutex will be acquired.
- Add function for getting the priority of a thread.
  An auxiliary function that translates the OS priority to the
  EAL accepted ones is added.
- Fix unit tests logging, add descriptive asserts that mark test failures.
  Verify mutex locking, verify barrier return values. Add test for
  statically initialized mutexes.
- Fix Alpine build by removing the use of pthread_attr_set_affinity() and
  using pthread_set_affinity() after the thread is created.

v14:
- Remove patch "eal: add EAL argument for setting thread priority"
  This will be added later when enabling the new threading API.
- Remove priority enum value "_UNDEFINED". NORMAL is used
  as the default.
- Fix issue with thread return value.

v13:
 - Fix syntax error in unit tests

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (9):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for mutex management
  eal: implement functions for thread barrier management
  Add unit tests for thread API

 app/test/meson.build            |   2 +
 app/test/test_threads.c         | 372 ++++++++++++++++++
 lib/eal/common/meson.build      |   1 +
 lib/eal/common/rte_thread.c     | 497 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    | 435 ++++++++++++++++++++-
 lib/eal/unix/meson.build        |   1 -
 lib/eal/unix/rte_thread.c       |  92 -----
 lib/eal/version.map             |  22 ++
 lib/eal/windows/eal_lcore.c     | 176 ++++++---
 lib/eal/windows/eal_windows.h   |  10 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 656 ++++++++++++++++++++++++++++++--
 12 files changed, 2093 insertions(+), 173 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:09                                         ` Thomas Monjalon
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
                                                         ` (9 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------
 lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 17 ++++++++
 6 files changed, 95 insertions(+), 32 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index 6d01b0f072..5299bb80d3 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -51,5 +51,6 @@ if not is_windows
             'hotplug_mp.c',
             'malloc_mp.c',
             'rte_keepalive.c',
+            'rte_thread.c'
     )
 endif
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..748f64d230 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 38f7de83e1..d1c313d519 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -420,6 +420,9 @@ EXPERIMENTAL {
 
 	# added in 21.08
 	rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..41c354818b 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,6 +12,22 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:12                                         ` Thomas Monjalon
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                         ` (8 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 91 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..e1a4d7eae4 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 748f64d230..4ac36957ce 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,28 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = 0,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +85,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index d1c313d519..a1b944788e 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 41c354818b..01966e7745 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+			     rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+			     enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:16                                         ` Thomas Monjalon
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                         ` (7 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  6 +--
 lib/eal/include/rte_thread.h |  5 +-
 lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index e1a4d7eae4..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	RTE_VERIFY(cpuset != NULL);
@@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 4ac36957ce..8a20215a94 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -233,9 +233,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 01966e7745..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
@@ -42,7 +90,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
 
 int
 rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 	thread_attr->cpuset = *cpuset;
@@ -52,7 +100,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
-			     rte_cpuset_t *cpuset)
+		rte_cpuset_t *cpuset)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -63,7 +111,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
 
 int
 rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
-			     enum rte_thread_priority priority)
+		enum rte_thread_priority priority)
 {
 	RTE_VERIFY(thread_attr != NULL);
 
@@ -76,18 +124,18 @@ int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -95,16 +143,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -115,17 +163,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -134,16 +179,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 4/9] eal: implement functions for thread affinity management
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (2 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:20                                         ` Thomas Monjalon
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                         ` (6 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8a20215a94..5b100cafda 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -85,6 +85,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a1b944788e..58b9553d59 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -427,6 +427,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 23ead6d30c..355ef181a5 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 5/9] eal: implement thread priority management functions
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (3 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                         ` (5 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for setting and getting the priority of a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  97 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  34 ++++++++++
 lib/eal/version.map          |   2 +
 lib/eal/windows/rte_thread.c | 127 +++++++++++++++++++++++++++++++++++
 4 files changed, 260 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..7ab08561a5 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,103 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_priority(int policy, int os_pri,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (policy) {
+	case SCHED_OTHER:
+		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case SCHED_RR:
+		if (os_pri == sched_get_priority_max(SCHED_RR)) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
+			&param);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
+		goto cleanup;
+	}
+
+	return thread_map_os_priority_to_eal_priority(policy,
+			param.sched_priority, priority);
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5b100cafda..7077c9ce46 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -213,6 +213,40 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Get the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get priority.
+ *
+ * @param priority
+ *   Location to store the retrieved priority.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority);
+
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 58b9553d59..dcc2c479e9 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,8 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_get_priority;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..5c02a6eaff 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,133 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_value(int os_pri, int pri_class,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (pri_class) {
+	case NORMAL_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_NORMAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case REALTIME_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	HANDLE thread_handle = NULL;
+	DWORD pri_class;
+	int os_pri;
+	int ret;
+
+	pri_class = GetPriorityClass(GetCurrentProcess());
+	if (pri_class == 0) {
+		ret = thread_log_last_error("GetPriorityClass()");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+			THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	os_pri = GetThreadPriority(thread_handle);
+	if (os_pri == THREAD_PRIORITY_ERROR_RETURN) {
+		ret = thread_log_last_error("GetThreadPriority()");
+		goto cleanup;
+	}
+
+	ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);
+	if (ret != 0)
+		goto cleanup;
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 6/9] eal: add thread lifetime management
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (4 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                                         ` (4 subsequent siblings)
  10 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 103 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 134 ++++++++++++++++++++++++++++++++
 5 files changed, 296 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 7ab08561a5..b3a9d4b47e 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -192,6 +192,109 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+				PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		ret = thread_map_priority_to_os_value(thread_attr->priority,
+				&param.sched_priority, &policy);
+		if (ret != 0)
+			goto cleanup;
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL && CPU_COUNT(&thread_attr->cpuset) > 0) {
+		ret = pthread_setaffinity_np((pthread_t)thread_id->opaque_id,
+				sizeof(thread_attr->cpuset),
+				&thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (value_ptr != NULL && *pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7077c9ce46..e841321819 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -211,6 +212,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index dcc2c479e9..ceaaf6b571 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -431,6 +431,9 @@ EXPERIMENTAL {
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index ff572b5dcb..8f0b3cb71e 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5c02a6eaff..669a68d6a8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -370,6 +375,135 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	return (DWORD)(uintptr_t)ctx.thread_func(ctx.routine_args);
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id,
+				thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (5 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:28                                         ` Thomas Monjalon
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                                         ` (3 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock, trylock.

Add RTE_STATIC_MUTEX macro to replace static initialization
of mutexes.
Windows does not have a static initializer.
Initialization is only done through InitializeCriticalSection().

The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
function that performs the actual mutex initialization.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  69 ++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 108 +++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |   5 ++
 lib/eal/windows/rte_thread.c |  64 +++++++++++++++++++++
 4 files changed, 246 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index b3a9d4b47e..476a8a1c08 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -295,6 +295,75 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_trylock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index e841321819..b5782d396f 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,26 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_STATIC_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -266,6 +286,28 @@ int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
 __rte_experimental
 int rte_thread_detach(rte_thread_t thread_id);
 
+/**
+ * Set core affinity of the current thread.
+ * Support both EAL and non-EAL thread and update TLS.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0; otherwise return -1;
+ */
+int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
+
+/**
+ * Get core affinity of the current thread.
+ *
+ * @param cpusetp
+ *   Pointer to CPU affinity of current thread.
+ *   It presumes input is not NULL, otherwise it causes panic.
+ *
+ */
+void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
@@ -302,6 +344,72 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Tries to lock a mutex.If the mutex is already held by a different thread,
+ * the function returns without blocking.
+ *
+ * @param mutex
+ *    The mutex that will be acquired, if not already locked.
+ *
+ * @return
+ *   On success, if the mutex is acquired, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_try_lock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ceaaf6b571..2506eb1587 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -434,6 +434,11 @@ EXPERIMENTAL {
 	rte_thread_create;
 	rte_thread_join;
 	rte_thread_detach;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_try_lock;
+	rte_thread_mutex_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 669a68d6a8..188e25e02e 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -504,6 +504,70 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (TryEnterCriticalSection(mutex->mutex_id) != 0)
+		return 0;
+
+	return EBUSY;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (6 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:32                                         ` Thomas Monjalon
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
                                                         ` (2 subsequent siblings)
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 476a8a1c08..580448d8bf 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -364,6 +364,67 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return ret;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index b5782d396f..0adc854225 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -74,6 +74,18 @@ typedef struct rte_thread_mutex_tag {
 	void *mutex_id;  /**< mutex identifier */
 } rte_thread_mutex;
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -410,6 +422,52 @@ int rte_thread_mutex_try_lock(rte_thread_mutex *mutex);
 __rte_experimental
 int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 2506eb1587..ca05ba4f43 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -439,6 +439,9 @@ EXPERIMENTAL {
 	rte_thread_mutex_unlock;
 	rte_thread_mutex_try_lock;
 	rte_thread_mutex_destroy;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 188e25e02e..11b4863fe8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -568,6 +568,62 @@ rte_thread_mutex_destroy(rte_thread_mutex *mutex)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (7 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-10-09  7:41                                       ` Narcisa Ana Maria Vasile
  2021-10-12 16:33                                         ` Thomas Monjalon
  2021-10-12 16:07                                       ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Thomas Monjalon
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
  10 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-10-09  7:41 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.
The tests verify that:
 * mutexes and barriers behave as expected
 * thread properties are applied correctly
 * the thread id is retrieved correctly
 * thread creation/destruction works properly

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |   2 +
 app/test/test_threads.c | 372 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 374 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f144d8b8ed..019c7e27d0 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -141,6 +141,7 @@ test_sources = files(
         'test_table_tables.c',
         'test_tailq.c',
         'test_thash.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -277,6 +278,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest', true],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..d125a55b2e
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <rte_thread.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO);
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	int ret;
+	int i;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		RTE_TEST_ASSERT(rte_thread_join(threads_ids[i], NULL) == 0, "Failed to join thread!");
+		RTE_TEST_ASSERT_EQUAL(threads_ids[i].opaque_id,
+				self_ids[i].opaque_id, "Unexpected thread id!");
+	}
+
+	return 0;
+}
+
+struct thread_context {
+	rte_thread_barrier *barrier;
+	int barrier_result;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+	struct thread_context *ctx = arg;
+
+	ctx->barrier_result = rte_thread_barrier_wait(ctx->barrier);
+	if (ctx->barrier_result > 0)
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to wait at barrier!");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t thread_id;
+	struct thread_context ctx;
+	rte_thread_barrier barrier;
+	int ret = 0;
+	int result = 0;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	ctx.barrier = &barrier;
+	ret = rte_thread_create(&thread_id, NULL, thread_loop_barrier, &ctx);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	result = rte_thread_barrier_wait(&barrier);
+	RTE_TEST_ASSERT(result <= 0, "Failed to wait at the barrier!");
+
+	ret = rte_thread_join(thread_id, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	RTE_TEST_ASSERT(ctx.barrier_result <= 0, "Child thread failed to wait at the barrier!");
+	RTE_TEST_ASSERT_NOT_EQUAL(ctx.barrier_result, result, "Threads were not blocked at the barrier!");
+
+	return 0;
+}
+
+RTE_STATIC_MUTEX(static_mutex);
+
+struct mutex_loop_args {
+	rte_thread_barrier *barrier;
+	rte_thread_mutex *mutex;
+	unsigned long result_A;
+	unsigned long result_B;
+};
+
+static void *
+thread_loop_mutex_B(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) == 0) {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_B = 1;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_B = 2;
+	}
+
+	return NULL;
+}
+
+static void *
+thread_loop_mutex_A(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) != 0) {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_A = 2;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_A = 1;
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(rte_thread_mutex *pmutex)
+{
+	rte_thread_t thread_A;
+	rte_thread_t thread_B;
+	rte_thread_mutex mutex;
+	rte_thread_barrier barrier;
+	struct mutex_loop_args args;
+	int ret = 0;
+
+	/* If mutex is not statically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_init(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to initialize mutex!");
+	} else
+		mutex = *pmutex;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	args.mutex = &mutex;
+	args.barrier = &barrier;
+
+	ret = rte_thread_create(&thread_A, NULL, thread_loop_mutex_A, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_create(&thread_B, NULL, thread_loop_mutex_B, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_join(thread_A, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	ret = rte_thread_join(thread_B, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	RTE_TEST_ASSERT(args.result_A != args.result_B, "Mutex failed to be acquired or was acquired by both threads!");
+
+	/* Destroy if dynamically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_destroy(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to destroy mutex!");
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	return ret;
+}
+
+static int
+test_thread_mutex_static(void)
+{
+	return test_thread_mutex(&static_mutex);
+}
+
+static int
+test_thread_mutex_dynamic(void)
+{
+	return test_thread_mutex(NULL);
+}
+
+struct thread_affinity_ctx {
+	rte_cpuset_t *cpuset;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0) {
+		ctx->result = 1;
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to get thread affinity!");
+		return NULL;
+	}
+
+	/*
+	 * Check that the thread is not running on CPUs which were not
+	 * specified in the affinity mask. Note that the CPU mask
+	 * retrieved above can be different than the original mask specified
+	 * with rte_thread_attr_set_affinity(), since some CPUs may not be
+	 * available on the system.
+	 */
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (!CPU_ISSET(i, ctx->cpuset) && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			rte_log(RTE_LOG_DEBUG, threads_logtype_test, "CPU %zu should not be set for this thread!\n",
+					i);
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize thread attributes!");
+
+	CPU_ZERO(&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
+	RTE_TEST_ASSERT(ret == 0, "Failed to get main thread affinity!");
+
+	ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread attributes!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].cpuset = &cpuset;
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity, &ctx[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(ctx[i].result, 0, "Unexpected thread affinity!");
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_priority(void *arg)
+{
+	int ret;
+	enum rte_thread_priority priority;
+	int *result = arg;
+
+	*result = 1;
+	ret = rte_thread_get_priority(rte_thread_self(), &priority);
+	if (ret != 0 || priority != RTE_THREAD_PRIORITY_NORMAL)
+		*result = 2;
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	int ret = 0;
+	int results[THREADS_COUNT] = {};
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize  thread attributes!");
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread priority!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_priority, &results[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(results[i], 1, "Unexpected priority value!");
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_detach(threads_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to detach thread!");
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex_static),
+			TEST_CASE(test_thread_mutex_dynamic),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (8 preceding siblings ...)
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-10-12 16:07                                       ` Thomas Monjalon
  2021-11-09  1:55                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
  10 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:07 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> EAL thread API
> 
> **Problem Statement**
> DPDK currently uses the pthread interface to create and manage threads.
> Windows does not support the POSIX thread programming model,
> so it currently
> relies on a header file that hides the Windows calls under
> pthread matched interfaces. Given that EAL should isolate the environment
> specifics from the applications and libraries and mediate
> all the communication with the operating systems, a new EAL interface
> is needed for thread management.
> 
> **Goals**
> * Introduce a generic EAL API for threading support that will remove
>   the current Windows pthread.h shim.
> * Replace references to pthread_* across the DPDK codebase with the new
>   RTE_THREAD_* API.
> * Allow users to choose between using the RTE_THREAD_* API or a
>   3rd party thread library through a configuration option.
> 
> **Design plan**
> New API main files:
> * rte_thread.h (librte_eal/include)
> * rte_thread.c (librte_eal/windows)
> * rte_thread.c (librte_eal/common)

Why this file is not in lib/eal/unix/ ?


> **A schematic example of the design**
> --------------------------------------------------
> lib/librte_eal/include/rte_thread.h
> int rte_thread_create();
> 
> lib/librte_eal/common/rte_thread.c
> int rte_thread_create() 
> {
> 	return pthread_create();
> }
> 
> lib/librte_eal/windows/rte_thread.c
> int rte_thread_create() 
> {
> 	return CreateThread();
> }
> -----------------------------------------------------

We must have the same error code, no matter the underlying implementation.
So you cannot return directly pthread or win32 error codes.


> **Thread attributes**
> 
> When or after a thread is created, specific characteristics of the thread
> can be adjusted. Given that the thread characteristics that are of interest
> for DPDK applications are affinity and priority, the following structure
> that represents thread attributes has been defined:
> 
> typedef struct
> {
> 	enum rte_thread_priority priority;
> 	rte_cpuset_t cpuset;
> } rte_thread_attr_t;
> 
> The *rte_thread_create()* function can optionally receive
> an rte_thread_attr_t
> object that will cause the thread to be created with the
> affinity and priority
> described by the attributes object. If no rte_thread_attr_t is passed
> (parameter is NULL), the default affinity and priority are used.
> An rte_thread_attr_t object can also be set to the default values
> by calling *rte_thread_attr_init()*.
> 
> *Priority* is represented through an enum that currently advertises
> two values for priority:
> 	- RTE_THREAD_PRIORITY_NORMAL
> 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

The priority level realtime should never used.

I am not sure about handling the priority so precisely.
I think we can abstract the priority need through different functions.
We already have the function rte_ctrl_thread_create() where priority
should be fixed.
I think we have only 2 types of threads:
	- control thread (interrupt, timer, IPC)
	- datapath lcore (created in rte_eal_init, including service cores)
It means we need only one new function for datapath thread creation.

> The enum can be extended to allow for multiple priority levels.
> rte_thread_set_priority      - sets the priority of a thread
> rte_thread_get_priority      - retrieves the priority of a thread
>                                from the OS
> rte_thread_attr_set_priority - updates an rte_thread_attr_t object
>                                with a new value for priority
> 
> The user can choose thread priority through an EAL parameter,
> when starting an application.  If EAL parameter is not used,
> the per-platform default value for thread priority is used.
> Otherwise administrator has an option to set one of available options:
>  --thread-prio normal
>  --thread-prio realtime

I don't think we need such feature.
Anyway, it is a new feature, so it is beyond the initial replacement goal.


> Example:
> ./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff
> 
> *Affinity* is described by the already known “rte_cpuset_t” type.
> rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
>                                    rte_thread_attr_t object
> rte_thread_set/get_affinity      – sets/gets the affinity of a thread
> 
> **Errors**
> A translation function that maps Windows error codes to errno-style
> error codes is provided. 
> 
> **Future work**
> The long term plan is for EAL to provide full threading support:
> * Add support for conditional variables
> * Additional functionality offered by pthread_*
>   (such as pthread_setname_np, etc.)




^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-10-12 16:09                                         ` Thomas Monjalon
  0 siblings, 0 replies; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:09 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Use a portable, type-safe representation for the thread identifier.
> Add functions for comparing thread ids and obtaining the thread id
> for the current thread.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/eal/common/meson.build            |  1 +
>  lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++-----------

There is no explanation about this move.

>  lib/eal/include/rte_thread.h          | 48 +++++++++++++++++-----
>  lib/eal/unix/meson.build              |  1 -
>  lib/eal/version.map                   |  3 ++
>  lib/eal/windows/rte_thread.c          | 17 ++++++++
>  6 files changed, 95 insertions(+), 32 deletions(-)
>  rename lib/eal/{unix => common}/rte_thread.c (66%)
[...]
> -	err = pthread_key_create(&((*key)->thread_index), destructor);
> -	if (err) {
> +	err = pthread_key_create(&(k->thread_index), destructor);
> +	if (err != 0) {

It looks wrong to call pthread functions in a "common" file.




^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-10-12 16:12                                         ` Thomas Monjalon
  2021-11-09  1:59                                           ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:12 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Implement thread attributes for:
> * thread affinity
> * thread priority
> Implement functions for managing thread attributes.
> 
> Priority is represented through an enum that allows for two levels:
> 	- RTE_THREAD_PRIORITY_NORMAL
> 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

It doesn't say how do you translate these priorites in POSIX and win32.

> Affinity is described by the rte_cpuset_t type.
> 
> An rte_thread_attr_t object can be set to the default values
> by calling rte_thread_attr_init().
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
[...]
>  lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
>  lib/eal/windows/rte_thread.c | 44 +++++++++++++++++

These 2 files look like code duplication.




^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-10-12 16:16                                         ` Thomas Monjalon
  2021-11-09  2:02                                           ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:16 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, talshn,
	ocardona, bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add function to translate Windows error codes to
> errno-style error codes. The possible return values are chosen
> so that we have as much semantical compatibility between platforms as
> possible.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/eal/common/rte_thread.c  |  6 +--
>  lib/eal/include/rte_thread.h |  5 +-
>  lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
>  3 files changed, 76 insertions(+), 30 deletions(-)
> 
> diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
> index e1a4d7eae4..27ad1c7eb0 100644
> --- a/lib/eal/common/rte_thread.c
> +++ b/lib/eal/common/rte_thread.c
> @@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
>  
>  int
>  rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
> -			     rte_cpuset_t *cpuset)
> +		rte_cpuset_t *cpuset)
>  {
>  	RTE_VERIFY(thread_attr != NULL);
>  	RTE_VERIFY(cpuset != NULL);
> @@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
>  
>  int
>  rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
> -			     rte_cpuset_t *cpuset)
> +		rte_cpuset_t *cpuset)
>  {
>  	RTE_VERIFY(thread_attr != NULL);
>  	RTE_VERIFY(cpuset != NULL);
> @@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
>  
>  int
>  rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
> -			     enum rte_thread_priority priority)
> +		enum rte_thread_priority priority)

Above are unrelated changes.

> --- a/lib/eal/windows/rte_thread.c
> +++ b/lib/eal/windows/rte_thread.c
> @@ -13,6 +13,54 @@ struct eal_tls_key {
>  	DWORD thread_index;
>  };
>  
> +/* Translates the most common error codes related to threads */
> +static int
> +thread_translate_win32_error(DWORD error)

So you decide to adopt POSIX error codes for the DPDK API. OK

> +{
> +	switch (error) {
> +	case ERROR_SUCCESS:
> +		return 0;
> +
> +	case ERROR_INVALID_PARAMETER:
> +		return EINVAL;
> +
> +	case ERROR_INVALID_HANDLE:
> +		return EFAULT;
> +
> +	case ERROR_NOT_ENOUGH_MEMORY:
> +	/* FALLTHROUGH */
> +	case ERROR_NO_SYSTEM_RESOURCES:
> +		return ENOMEM;
> +
> +	case ERROR_PRIVILEGE_NOT_HELD:
> +	/* FALLTHROUGH */
> +	case ERROR_ACCESS_DENIED:
> +		return EACCES;
> +
> +	case ERROR_ALREADY_EXISTS:
> +		return EEXIST;
> +
> +	case ERROR_POSSIBLE_DEADLOCK:
> +		return EDEADLK;
> +
> +	case ERROR_INVALID_FUNCTION:
> +	/* FALLTHROUGH */
> +	case ERROR_CALL_NOT_IMPLEMENTED:
> +		return ENOSYS;
> +	}
> +
> +	return EINVAL;
> +}
[...]
>  rte_thread_key_create(rte_thread_key *key,
>  		__rte_unused void (*destructor)(void *))
>  {
> +	int ret;
> +
>  	*key = malloc(sizeof(**key));
>  	if ((*key) == NULL) {
>  		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
> -		rte_errno = ENOMEM;
> -		return -1;
> +		return ENOMEM;
>  	}

Why this change? rte_errno and negative error code are good.




^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 4/9] eal: implement functions for thread affinity management
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-10-12 16:20                                         ` Thomas Monjalon
  0 siblings, 0 replies; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:20 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Implement functions for getting/setting thread affinity.
> Threads can be pinned to specific cores by setting their
> affinity attribute.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
[...]
> +/**
> + * Set the affinity of thread 'thread_id' to the cpu set
> + * specified by 'cpuset'.
> + *
> + * @param thread_id
> + *    Id of the thread for which to set the affinity.
> + *
> + * @param cpuset
> + *   Pointer to CPU affinity to set.
> + *
> + * @return
> + *   On success, return 0.
> + *   On failure, return a positive errno-style error number.

Usually we return negative numbers on error.




^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-10-12 16:28                                         ` Thomas Monjalon
  2021-11-09  2:04                                           ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:28 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add functions for mutex init, destroy, lock, unlock, trylock.
> 
> Add RTE_STATIC_MUTEX macro to replace static initialization
> of mutexes.
> Windows does not have a static initializer.
> Initialization is only done through InitializeCriticalSection().
> 
> The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
> function that performs the actual mutex initialization.
[...]
> --- a/lib/eal/include/rte_thread.h
> +++ b/lib/eal/include/rte_thread.h
> +#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
> +
> +#define RTE_DEFINE_MUTEX(private_lock)\
> +RTE_INIT(__rte_ ## private_lock ## _init)\
> +{\
> +	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
> +}
> +
> +#define RTE_STATIC_MUTEX(private_lock)\
> +static RTE_DECLARE_MUTEX(private_lock);\
> +RTE_DEFINE_MUTEX(private_lock)

This is not truly static.
It is a wrapper to init the mutex in the constructor.
Should we rename?



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-10-12 16:32                                         ` Thomas Monjalon
  2021-11-09  2:07                                           ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:32 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add functions for barrier init, destroy, wait.
> 
> A portable type is used to represent a barrier identifier.
> The rte_thread_barrier_wait() function returns the same value
> on all platforms.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---
>  lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
>  lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
>  lib/eal/version.map          |  3 ++
>  lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
>  4 files changed, 178 insertions(+)

It doesn't need to be part of the API.
The pthread barrier is used only as part of the control thread implementation.
The need disappear if you implement control thread on Windows.



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API
  2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
@ 2021-10-12 16:33                                         ` Thomas Monjalon
  2021-11-09  2:10                                           ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-10-12 16:33 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/10/2021 09:41, Narcisa Ana Maria Vasile:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> As a new API for threading is introduced,
> a set of unit tests have been added to test the new interface.
> The tests verify that:
>  * mutexes and barriers behave as expected
>  * thread properties are applied correctly
>  * the thread id is retrieved correctly
>  * thread creation/destruction works properly

Please make each test part of the patch implementing the feature.
Thanks



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading
  2021-10-12 16:07                                       ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Thomas Monjalon
@ 2021-11-09  1:55                                         ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-09  1:55 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Tue, Oct 12, 2021 at 06:07:06PM +0200, Thomas Monjalon wrote:
> 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > EAL thread API
> > 
> > **Problem Statement**
> > DPDK currently uses the pthread interface to create and manage threads.
> > Windows does not support the POSIX thread programming model,
> > so it currently
> > relies on a header file that hides the Windows calls under
> > pthread matched interfaces. Given that EAL should isolate the environment
> > specifics from the applications and libraries and mediate
> > all the communication with the operating systems, a new EAL interface
> > is needed for thread management.
> > 
> > **Goals**
> > * Introduce a generic EAL API for threading support that will remove
> >   the current Windows pthread.h shim.
> > * Replace references to pthread_* across the DPDK codebase with the new
> >   RTE_THREAD_* API.
> > * Allow users to choose between using the RTE_THREAD_* API or a
> >   3rd party thread library through a configuration option.
> > 
> > **Design plan**
> > New API main files:
> > * rte_thread.h (librte_eal/include)
> > * rte_thread.c (librte_eal/windows)
> > * rte_thread.c (librte_eal/common)
> 
> Why this file is not in lib/eal/unix/ ?
> 
  
  Thank you Thomas for reviewing these patches!
  Your guidance is very much appreciated as I want to bring this patchset on the
  good path towards merging.
  Based on community meeting discussions, multiple users have requested an option
  to allow them to use a 3rd party thread library. At the same time, we want to remove
  the Windows shim that we currently use for threading in DPDK,
  so we decided to do the following:
  
  A new rte_thread_* API is introduced, which will be used uniformly across DPDK.
	  - for unix-based platforms, the code in eal/common will be compiled
	  - for windows, the code in eal/windows will be compiled.
  For all cases when a 3rd party library is needed, the code from eal/common will be
  used. For example, if winpthreads or pthreads4w are used, at build time the code from
  'eal/common' will be selected and the rte_thread_* API will point to pthread_*
  functions described by the "pthread.h" header file provided by the 3rd party library.
 
  Using a 3rd party library will not require any changes in the DPDK code,
  except for adding an option in the meson files. 
  Therefore code from common will work both on unix and windows.
  Nick explains even better in his RFC from that time: [RFC] pthread on Windows - Patchwork (dpdk.org).
  
  I will improve the cover letter and the commit messages to better explain this.
> 
> > **A schematic example of the design**
> > --------------------------------------------------
> > lib/librte_eal/include/rte_thread.h
> > int rte_thread_create();
> > 
> > lib/librte_eal/common/rte_thread.c
> > int rte_thread_create() 
> > {
> > 	return pthread_create();
> > }
> > 
> > lib/librte_eal/windows/rte_thread.c
> > int rte_thread_create() 
> > {
> > 	return CreateThread();
> > }
> > -----------------------------------------------------
> 
> We must have the same error code, no matter the underlying implementation.
> So you cannot return directly pthread or win32 error codes.
> 

  The approach here is to translate the Windows errors to POSIX-style ones to have
  uniformity across the entire threading module.

> 
> > **Thread attributes**
> > 
> > When or after a thread is created, specific characteristics of the thread
> > can be adjusted. Given that the thread characteristics that are of interest
> > for DPDK applications are affinity and priority, the following structure
> > that represents thread attributes has been defined:
> > 
> > typedef struct
> > {
> > 	enum rte_thread_priority priority;
> > 	rte_cpuset_t cpuset;
> > } rte_thread_attr_t;
> > 
> > The *rte_thread_create()* function can optionally receive
> > an rte_thread_attr_t
> > object that will cause the thread to be created with the
> > affinity and priority
> > described by the attributes object. If no rte_thread_attr_t is passed
> > (parameter is NULL), the default affinity and priority are used.
> > An rte_thread_attr_t object can also be set to the default values
> > by calling *rte_thread_attr_init()*.
> > 
> > *Priority* is represented through an enum that currently advertises
> > two values for priority:
> > 	- RTE_THREAD_PRIORITY_NORMAL
> > 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
> 
> The priority level realtime should never used.
> 
> I am not sure about handling the priority so precisely.
> I think we can abstract the priority need through different functions.
> We already have the function rte_ctrl_thread_create() where priority
> should be fixed.
> I think we have only 2 types of threads:
> 	- control thread (interrupt, timer, IPC)
> 	- datapath lcore (created in rte_eal_init, including service cores)
> It means we need only one new function for datapath thread creation.
> 

I'll explain better the intent here on you other comment in patch 2. 

> > The enum can be extended to allow for multiple priority levels.
> > rte_thread_set_priority      - sets the priority of a thread
> > rte_thread_get_priority      - retrieves the priority of a thread
> >                                from the OS
> > rte_thread_attr_set_priority - updates an rte_thread_attr_t object
> >                                with a new value for priority
> > 
> > The user can choose thread priority through an EAL parameter,
> > when starting an application.  If EAL parameter is not used,
> > the per-platform default value for thread priority is used.
> > Otherwise administrator has an option to set one of available options:
> >  --thread-prio normal
> >  --thread-prio realtime
> 
> I don't think we need such feature.
> Anyway, it is a new feature, so it is beyond the initial replacement goal.
> 
> 

  True, this is not part of this patchset, I will correct the cover letter.
  
> > Example:
> > ./dpdk-l2fwd -l 0-3 -n 4 –thread-prio normal -- -q 8 -p ffff
> > 
> > *Affinity* is described by the already known “rte_cpuset_t” type.
> > rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
> >                                    rte_thread_attr_t object
> > rte_thread_set/get_affinity      – sets/gets the affinity of a thread
> > 
> > **Errors**
> > A translation function that maps Windows error codes to errno-style
> > error codes is provided. 
> > 
> > **Future work**
> > The long term plan is for EAL to provide full threading support:
> > * Add support for conditional variables
> > * Additional functionality offered by pthread_*
> >   (such as pthread_setname_np, etc.)
> 
> 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-10-12 16:12                                         ` Thomas Monjalon
@ 2021-11-09  1:59                                           ` Narcisa Ana Maria Vasile
  2021-11-09  8:27                                             ` Thomas Monjalon
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-09  1:59 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Tue, Oct 12, 2021 at 06:12:21PM +0200, Thomas Monjalon wrote:
> 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Implement thread attributes for:
> > * thread affinity
> > * thread priority
> > Implement functions for managing thread attributes.
> > 
> > Priority is represented through an enum that allows for two levels:
> > 	- RTE_THREAD_PRIORITY_NORMAL
> > 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
> 
> It doesn't say how do you translate these priorites in POSIX and win32.

  I'll send a new version with a better commit message.
  Thread priorities on both Linux-based and Windows platforms are similarly
  constructed from a class/policy + priority value. Currently in DPDK, most threads
  operate at the OS-default priority level but there are cases when increasing the
  priority is useful. For example, the Mellanox data path acceleration driver requires
  realtime thread priority. Similarly, some Windows applications will require elevated
  priority.
  For these reasons, EAL will advertise 2 priority levels which are named suggestively
  "normal" and "realtime_critical" and are computed as follows:

  For Linux and similar platforms:
    * EAL "normal" priority corresponds to the (default) SCHED_OTHER policy + a priority value of
      (sched_get_priority_min(SCHED_OTHER) + sched_get_priority_max(SCHED_OTHER))/2.
      Note that on Linux the resulting priority value will be 0,
      in accordance to the docs guidance that mention the value should be 0 for SCHED_OTHER policy.
	
    * EAL "realtime" priority corresponds to the SCHED_RR policy + a priority value of 
      sched_get_priority_max(SCHED_RR);

  For Windows:
    * EAL "normal" corresponds to class NORMAL_PRIORITY_CLASS +
      priority THREAD_PRIORITY_NORMAL
    * EAL "realtime_critical" corresponds to class REALTIME_PRIORITY_CLASS +
      priority THREAD_PRIORITY_TIME_CRITICAL
> 
> > Affinity is described by the rte_cpuset_t type.
> > 
> > An rte_thread_attr_t object can be set to the default values
> > by calling rte_thread_attr_init().
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> [...]
> >  lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
> >  lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
> 
> These 2 files look like code duplication.
> 
> 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-10-12 16:16                                         ` Thomas Monjalon
@ 2021-11-09  2:02                                           ` Narcisa Ana Maria Vasile
  2021-11-09  8:21                                             ` Thomas Monjalon
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-09  2:02 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, talshn,
	ocardona, bruce.richardson, david.marchand, pallavi.kadam

On Tue, Oct 12, 2021 at 06:16:19PM +0200, Thomas Monjalon wrote:
> 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Add function to translate Windows error codes to
> > errno-style error codes. The possible return values are chosen
> > so that we have as much semantical compatibility between platforms as
> > possible.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
> >  lib/eal/common/rte_thread.c  |  6 +--
> >  lib/eal/include/rte_thread.h |  5 +-
> >  lib/eal/windows/rte_thread.c | 95 +++++++++++++++++++++++++++---------
> >  3 files changed, 76 insertions(+), 30 deletions(-)
> > 
> > diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
> > index e1a4d7eae4..27ad1c7eb0 100644
> > --- a/lib/eal/common/rte_thread.c
> > +++ b/lib/eal/common/rte_thread.c
> > @@ -47,7 +47,7 @@ rte_thread_attr_init(rte_thread_attr_t *attr)
> >  
> >  int
> >  rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
> > -			     rte_cpuset_t *cpuset)
> > +		rte_cpuset_t *cpuset)
> >  {
> >  	RTE_VERIFY(thread_attr != NULL);
> >  	RTE_VERIFY(cpuset != NULL);
> > @@ -59,7 +59,7 @@ rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
> >  
> >  int
> >  rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
> > -			     rte_cpuset_t *cpuset)
> > +		rte_cpuset_t *cpuset)
> >  {
> >  	RTE_VERIFY(thread_attr != NULL);
> >  	RTE_VERIFY(cpuset != NULL);
> > @@ -71,7 +71,7 @@ rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
> >  
> >  int
> >  rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
> > -			     enum rte_thread_priority priority)
> > +		enum rte_thread_priority priority)
> 
> Above are unrelated changes.
> 

  Thanks, will fix!

> > --- a/lib/eal/windows/rte_thread.c
> > +++ b/lib/eal/windows/rte_thread.c
> > @@ -13,6 +13,54 @@ struct eal_tls_key {
> >  	DWORD thread_index;
> >  };
> >  
> > +/* Translates the most common error codes related to threads */
> > +static int
> > +thread_translate_win32_error(DWORD error)
> 
> So you decide to adopt POSIX error codes for the DPDK API. OK
> 
> > +{
> > +	switch (error) {
> > +	case ERROR_SUCCESS:
> > +		return 0;
> > +
> > +	case ERROR_INVALID_PARAMETER:
> > +		return EINVAL;
> > +
> > +	case ERROR_INVALID_HANDLE:
> > +		return EFAULT;
> > +
> > +	case ERROR_NOT_ENOUGH_MEMORY:
> > +	/* FALLTHROUGH */
> > +	case ERROR_NO_SYSTEM_RESOURCES:
> > +		return ENOMEM;
> > +
> > +	case ERROR_PRIVILEGE_NOT_HELD:
> > +	/* FALLTHROUGH */
> > +	case ERROR_ACCESS_DENIED:
> > +		return EACCES;
> > +
> > +	case ERROR_ALREADY_EXISTS:
> > +		return EEXIST;
> > +
> > +	case ERROR_POSSIBLE_DEADLOCK:
> > +		return EDEADLK;
> > +
> > +	case ERROR_INVALID_FUNCTION:
> > +	/* FALLTHROUGH */
> > +	case ERROR_CALL_NOT_IMPLEMENTED:
> > +		return ENOSYS;
> > +	}
> > +
> > +	return EINVAL;
> > +}
> [...]
> >  rte_thread_key_create(rte_thread_key *key,
> >  		__rte_unused void (*destructor)(void *))
> >  {
> > +	int ret;
> > +
> >  	*key = malloc(sizeof(**key));
> >  	if ((*key) == NULL) {
> >  		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
> > -		rte_errno = ENOMEM;
> > -		return -1;
> > +		return ENOMEM;
> >  	}
> 
> Why this change? rte_errno and negative error code are good.
> 

  This error could have been handled using rte_errno and negative return,
  but for consistency, a positive error number is returned. As different platforms
  have different error codes, the approach here is to translate the Windows error
  to POSIX-style ones to have uniformity over the values returned. All functions
  in this thread module return the possible error through the return value.

> 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management
  2021-10-12 16:28                                         ` Thomas Monjalon
@ 2021-11-09  2:04                                           ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-09  2:04 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Tue, Oct 12, 2021 at 06:28:56PM +0200, Thomas Monjalon wrote:
> 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Add functions for mutex init, destroy, lock, unlock, trylock.
> > 
> > Add RTE_STATIC_MUTEX macro to replace static initialization
> > of mutexes.
> > Windows does not have a static initializer.
> > Initialization is only done through InitializeCriticalSection().
> > 
> > The RTE_STATIC_MUTEX calls into the rte_thread_mutex_init()
> > function that performs the actual mutex initialization.
> [...]
> > --- a/lib/eal/include/rte_thread.h
> > +++ b/lib/eal/include/rte_thread.h
> > +#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
> > +
> > +#define RTE_DEFINE_MUTEX(private_lock)\
> > +RTE_INIT(__rte_ ## private_lock ## _init)\
> > +{\
> > +	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
> > +}
> > +
> > +#define RTE_STATIC_MUTEX(private_lock)\
> > +static RTE_DECLARE_MUTEX(private_lock);\
> > +RTE_DEFINE_MUTEX(private_lock)
> 
> This is not truly static.
> It is a wrapper to init the mutex in the constructor.
> Should we rename?
> 

Agreed, I'll rename to RTE_MUTEX_INIT or something like this.
Thanks!

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management
  2021-10-12 16:32                                         ` Thomas Monjalon
@ 2021-11-09  2:07                                           ` Narcisa Ana Maria Vasile
  2021-11-10  3:13                                             ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-09  2:07 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Tue, Oct 12, 2021 at 06:32:09PM +0200, Thomas Monjalon wrote:
> 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > Add functions for barrier init, destroy, wait.
> > 
> > A portable type is used to represent a barrier identifier.
> > The rte_thread_barrier_wait() function returns the same value
> > on all platforms.
> > 
> > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > ---
> >  lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
> >  lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
> >  lib/eal/version.map          |  3 ++
> >  lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
> >  4 files changed, 178 insertions(+)
> 
> It doesn't need to be part of the API.
> The pthread barrier is used only as part of the control thread implementation.
> The need disappear if you implement control thread on Windows.
> 
Actually I think I have the implementation already. I've worked at this some time ago,
I have this patch:
[v4,2/6] eal: add function for control thread creation

The issue is I will break ABI so I cannot merge it as part of this patchset.
I'll see if I can remove this barrier patch though.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API
  2021-10-12 16:33                                         ` Thomas Monjalon
@ 2021-11-09  2:10                                           ` Narcisa Ana Maria Vasile
  2021-11-09  8:32                                             ` Thomas Monjalon
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-09  2:10 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Tue, Oct 12, 2021 at 06:33:16PM +0200, Thomas Monjalon wrote:
> 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > From: Narcisa Vasile <navasile@microsoft.com>
> > 
> > As a new API for threading is introduced,
> > a set of unit tests have been added to test the new interface.
> > The tests verify that:
> >  * mutexes and barriers behave as expected
> >  * thread properties are applied correctly
> >  * the thread id is retrieved correctly
> >  * thread creation/destruction works properly
> 
> Please make each test part of the patch implementing the feature.
> Thanks
> 
Makes sense, but most of these unit tests use rte_thread_create and
rte_thread_join to handle the creation and cleanup of the threads
that are being tested, so I'm forced to have this test patch at the end.
I could still break it up into smaller patches, one for each test category
(mutex, attributes, etc) if you want. 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors
  2021-11-09  2:02                                           ` Narcisa Ana Maria Vasile
@ 2021-11-09  8:21                                             ` Thomas Monjalon
  0 siblings, 0 replies; 290+ messages in thread
From: Thomas Monjalon @ 2021-11-09  8:21 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, talshn,
	ocardona, bruce.richardson, david.marchand, pallavi.kadam

09/11/2021 03:02, Narcisa Ana Maria Vasile:
> On Tue, Oct 12, 2021 at 06:16:19PM +0200, Thomas Monjalon wrote:
> > 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > >  rte_thread_key_create(rte_thread_key *key,
> > >  		__rte_unused void (*destructor)(void *))
> > >  {
> > > +	int ret;
> > > +
> > >  	*key = malloc(sizeof(**key));
> > >  	if ((*key) == NULL) {
> > >  		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
> > > -		rte_errno = ENOMEM;
> > > -		return -1;
> > > +		return ENOMEM;
> > >  	}
> > 
> > Why this change? rte_errno and negative error code are good.
> > 
> 
>   This error could have been handled using rte_errno and negative return,
>   but for consistency, a positive error number is returned. As different platforms
>   have different error codes, the approach here is to translate the Windows error
>   to POSIX-style ones to have uniformity over the values returned. All functions
>   in this thread module return the possible error through the return value.

We can have the same consistency with rte_errno.
What others think? Should we use rte_errno?



^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-11-09  1:59                                           ` Narcisa Ana Maria Vasile
@ 2021-11-09  8:27                                             ` Thomas Monjalon
  2021-11-10  3:04                                               ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-11-09  8:27 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam, stephen

09/11/2021 02:59, Narcisa Ana Maria Vasile:
> On Tue, Oct 12, 2021 at 06:12:21PM +0200, Thomas Monjalon wrote:
> > 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > > 
> > > Implement thread attributes for:
> > > * thread affinity
> > > * thread priority
> > > Implement functions for managing thread attributes.
> > > 
> > > Priority is represented through an enum that allows for two levels:
> > > 	- RTE_THREAD_PRIORITY_NORMAL
> > > 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
> > 
> > It doesn't say how do you translate these priorites in POSIX and win32.
> 
>   I'll send a new version with a better commit message.
>   Thread priorities on both Linux-based and Windows platforms are similarly
>   constructed from a class/policy + priority value. Currently in DPDK, most threads
>   operate at the OS-default priority level but there are cases when increasing the
>   priority is useful. For example, the Mellanox data path acceleration driver requires
>   realtime thread priority. Similarly, some Windows applications will require elevated
>   priority.

It should not. We should not use realtime priority.

>   For these reasons, EAL will advertise 2 priority levels which are named suggestively
>   "normal" and "realtime_critical" and are computed as follows:
> 
>   For Linux and similar platforms:
>     * EAL "normal" priority corresponds to the (default) SCHED_OTHER policy + a priority value of
>       (sched_get_priority_min(SCHED_OTHER) + sched_get_priority_max(SCHED_OTHER))/2.
>       Note that on Linux the resulting priority value will be 0,
>       in accordance to the docs guidance that mention the value should be 0 for SCHED_OTHER policy.
> 	
>     * EAL "realtime" priority corresponds to the SCHED_RR policy + a priority value of 
>       sched_get_priority_max(SCHED_RR);
> 
>   For Windows:
>     * EAL "normal" corresponds to class NORMAL_PRIORITY_CLASS +
>       priority THREAD_PRIORITY_NORMAL
>     * EAL "realtime_critical" corresponds to class REALTIME_PRIORITY_CLASS +
>       priority THREAD_PRIORITY_TIME_CRITICAL




^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API
  2021-11-09  2:10                                           ` Narcisa Ana Maria Vasile
@ 2021-11-09  8:32                                             ` Thomas Monjalon
  2021-11-10  3:07                                               ` Narcisa Ana Maria Vasile
  0 siblings, 1 reply; 290+ messages in thread
From: Thomas Monjalon @ 2021-11-09  8:32 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

09/11/2021 03:10, Narcisa Ana Maria Vasile:
> On Tue, Oct 12, 2021 at 06:33:16PM +0200, Thomas Monjalon wrote:
> > 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > > 
> > > As a new API for threading is introduced,
> > > a set of unit tests have been added to test the new interface.
> > > The tests verify that:
> > >  * mutexes and barriers behave as expected
> > >  * thread properties are applied correctly
> > >  * the thread id is retrieved correctly
> > >  * thread creation/destruction works properly
> > 
> > Please make each test part of the patch implementing the feature.
> > Thanks
> > 
> Makes sense, but most of these unit tests use rte_thread_create and
> rte_thread_join to handle the creation and cleanup of the threads
> that are being tested, so I'm forced to have this test patch at the end.

You mean you cannot start the series with implementing these 2 functions?

> I could still break it up into smaller patches, one for each test category
> (mutex, attributes, etc) if you want. 

I would like to see features built & tested atomically and progressively.



^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 00/13]  eal: Add EAL API for threading
  2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
                                                         ` (9 preceding siblings ...)
  2021-10-12 16:07                                       ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Thomas Monjalon
@ 2021-11-10  3:01                                       ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 01/13] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                           ` (14 more replies)
  10 siblings, 15 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Currently in DPDK most threads operate at the OS-default
priority level but there are cases when increasing the priority is useful.
For example, high-performance applications require elevated priority to
avoid being preempted by other threads on the system.
The following structure that represents thread attributes has been
defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_get_priority      - retrieves the priority of a thread
                               from the OS
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
As different platforms have different error codes, the approach here
is to translate the Windows error to POSIX-style ones to have
uniformity over the values returned. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v17:
 - Move unrelated changes to the correct patch.
 - Rename RTE_STATIC_MUTEX to avoid confusion, since
   the mutex is still dynamically initialized behind the scenes.
 - Break down the unit tests into smaller patches and reorder them.
 - Remove duplicated code in header.
 - Improve commit messages and cover letter.

v16:
- Fix warning on freebsd by adding cast
- Change affinity unit test to consider ases when the requested CPU
  are not available on the system.
- Fix priority unit test to avoid termination of thread before the
  priority is checked.

v15:
- Add try_lock mutex functionality. If the mutex is already owned by a
  different thread, the function returns immediately. Otherwise, 
  the mutex will be acquired.
- Add function for getting the priority of a thread.
  An auxiliary function that translates the OS priority to the
  EAL accepted ones is added.
- Fix unit tests logging, add descriptive asserts that mark test failures.
  Verify mutex locking, verify barrier return values. Add test for
  statically initialized mutexes.
- Fix Alpine build by removing the use of pthread_attr_set_affinity() and
  using pthread_set_affinity() after the thread is created.

v14:
- Remove patch "eal: add EAL argument for setting thread priority"
  This will be added later when enabling the new threading API.
- Remove priority enum value "_UNDEFINED". NORMAL is used
  as the default.
- Fix issue with thread return value.

v13:
 - Fix syntax error in unit tests

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (13):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  app/test: add unit tests for rte_thread_self
  app/test: add unit tests for thread attributes
  app/test: add unit tests for thread lifetime management
  eal: implement functions for thread barrier management
  app/test: add unit tests for barrier
  eal: implement functions for mutex management
  app/test: add unit tests for mutex

 app/test/meson.build            |   2 +
 app/test/test_threads.c         | 372 ++++++++++++++++++
 lib/eal/common/meson.build      |   1 +
 lib/eal/common/rte_thread.c     | 497 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    | 412 +++++++++++++++++++-
 lib/eal/unix/meson.build        |   1 -
 lib/eal/unix/rte_thread.c       |  92 -----
 lib/eal/version.map             |  22 ++
 lib/eal/windows/eal_lcore.c     | 176 ++++++---
 lib/eal/windows/eal_windows.h   |  10 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 656 ++++++++++++++++++++++++++++++--
 12 files changed, 2070 insertions(+), 173 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 01/13] eal: add basic threading functions
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 02/13] eal: add thread attributes Narcisa Ana Maria Vasile
                                                           ` (13 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++----------
 lib/eal/include/rte_thread.h          | 53 ++++++++++++++++++------
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 58 +++++++++++++++++----------
 6 files changed, 117 insertions(+), 56 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index 917758cc65..6bdc9cd854 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -52,5 +52,6 @@ if not is_windows
             'hotplug_mp.c',
             'malloc_mp.c',
             'rte_keepalive.c',
+            'rte_thread.c'
     )
 endif
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..c9cdeb07aa 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
@@ -112,9 +142,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ab28c22791..24e9747795 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -420,6 +420,9 @@ EXPERIMENTAL {
 	rte_intr_instance_free;
 	rte_intr_type_get;
 	rte_intr_type_set;
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..26c8dd4ebe 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,22 +12,38 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -34,16 +51,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -54,17 +71,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -73,16 +87,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 02/13] eal: add thread attributes
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 01/13] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 03/13] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                           ` (12 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 91 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index c9cdeb07aa..8a20215a94 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,28 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = 0,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +85,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 24e9747795..3fc33fcd70 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 26c8dd4ebe..f65919f46d 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 03/13] eal/windows: translate Windows errors to errno-style errors
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 01/13] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 02/13] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 04/13] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                           ` (11 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/windows/rte_thread.c | 48 ++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index f65919f46d..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 04/13] eal: implement functions for thread affinity management
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (2 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 03/13] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 05/13] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                           ` (10 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8a20215a94..5b100cafda 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -85,6 +85,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 3fc33fcd70..193a79a4d2 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -427,6 +427,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 23ead6d30c..355ef181a5 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 05/13] eal: implement thread priority management functions
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (3 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 04/13] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 06/13] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                           ` (9 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for setting and getting the priority of a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

Currently in DPDK most threads operate at the OS-default
priority level but there are cases when increasing the
priority is useful. For example, high performance applications
may require elevated priority levels.

For these reasons, EAL will expose two priority levels which
are named suggestively "normal" and "realtime_critical"
and are computed as follows:

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Note that on Linux the resulting priority value will be 0,
in accordance to the docs that mention the value
should be 0 for SCHED_OTHER policy.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  |  97 ++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  34 ++++++++++
 lib/eal/version.map          |   2 +
 lib/eal/windows/rte_thread.c | 127 +++++++++++++++++++++++++++++++++++
 4 files changed, 260 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..7ab08561a5 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,103 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_priority(int policy, int os_pri,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (policy) {
+	case SCHED_OTHER:
+		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case SCHED_RR:
+		if (os_pri == sched_get_priority_max(SCHED_RR)) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
+			&param);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
+		goto cleanup;
+	}
+
+	return thread_map_os_priority_to_eal_priority(policy,
+			param.sched_priority, priority);
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5b100cafda..7077c9ce46 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -213,6 +213,40 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Get the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get priority.
+ *
+ * @param priority
+ *   Location to store the retrieved priority.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority);
+
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 193a79a4d2..5bc5a6cf76 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,8 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_get_priority;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..5c02a6eaff 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,133 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_value(int os_pri, int pri_class,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (pri_class) {
+	case NORMAL_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_NORMAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case REALTIME_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	HANDLE thread_handle = NULL;
+	DWORD pri_class;
+	int os_pri;
+	int ret;
+
+	pri_class = GetPriorityClass(GetCurrentProcess());
+	if (pri_class == 0) {
+		ret = thread_log_last_error("GetPriorityClass()");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+			THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	os_pri = GetThreadPriority(thread_handle);
+	if (os_pri == THREAD_PRIORITY_ERROR_RETURN) {
+		ret = thread_log_last_error("GetThreadPriority()");
+		goto cleanup;
+	}
+
+	ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);
+	if (ret != 0)
+		goto cleanup;
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 06/13] eal: add thread lifetime management
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (4 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 05/13] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 07/13] app/test: add unit tests for rte_thread_self Narcisa Ana Maria Vasile
                                                           ` (8 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c     | 103 ++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 +++++++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 134 ++++++++++++++++++++++++++++++++
 5 files changed, 296 insertions(+), 1 deletion(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 7ab08561a5..b3a9d4b47e 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -192,6 +192,109 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+				PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+		ret = thread_map_priority_to_os_value(thread_attr->priority,
+				&param.sched_priority, &policy);
+		if (ret != 0)
+			goto cleanup;
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL && CPU_COUNT(&thread_attr->cpuset) > 0) {
+		ret = pthread_setaffinity_np((pthread_t)thread_id->opaque_id,
+				sizeof(thread_attr->cpuset),
+				&thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_setaffinity_np failed\n");
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (value_ptr != NULL && *pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7077c9ce46..e841321819 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -211,6 +212,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 5bc5a6cf76..0384a09fa2 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -431,6 +431,9 @@ EXPERIMENTAL {
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index bc31cc8465..912fed12c2 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5c02a6eaff..669a68d6a8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -370,6 +375,135 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	return (DWORD)(uintptr_t)ctx.thread_func(ctx.routine_args);
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id,
+				thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 07/13] app/test: add unit tests for rte_thread_self
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (5 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 06/13] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 08/13] app/test: add unit tests for thread attributes Narcisa Ana Maria Vasile
                                                           ` (7 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.
Test the rte_thread_self() functionality used
to retrieve the thread id.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build    |  2 ++
 app/test/test_threads.c | 63 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index 96670c3504..9fd34459e9 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -146,6 +146,7 @@ test_sources = files(
         'test_tailq.c',
         'test_thash.c',
         'test_thash_perf.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -287,6 +288,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest', true],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..e7ee50741c
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <rte_thread.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO);
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	int ret;
+	int i;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		RTE_TEST_ASSERT(rte_thread_join(threads_ids[i], NULL) == 0, "Failed to join thread!");
+		RTE_TEST_ASSERT_EQUAL(threads_ids[i].opaque_id,
+				self_ids[i].opaque_id, "Unexpected thread id!");
+	}
+
+	return 0;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 08/13] app/test: add unit tests for thread attributes
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (6 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 07/13] app/test: add unit tests for rte_thread_self Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 09/13] app/test: add unit tests for thread lifetime management Narcisa Ana Maria Vasile
                                                           ` (6 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Verify that affinity and priority can be set successfully.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/test_threads.c | 125 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)

diff --git a/app/test/test_threads.c b/app/test/test_threads.c
index e7ee50741c..53e5892793 100644
--- a/app/test/test_threads.c
+++ b/app/test/test_threads.c
@@ -44,12 +44,137 @@ test_thread_self(void)
 	return 0;
 }
 
+struct thread_affinity_ctx {
+	rte_cpuset_t *cpuset;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0) {
+		ctx->result = 1;
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to get thread affinity!");
+		return NULL;
+	}
+
+	/*
+	 * Check that the thread is not running on CPUs which were not
+	 * specified in the affinity mask. Note that the CPU mask
+	 * retrieved above can be different than the original mask specified
+	 * with rte_thread_attr_set_affinity(), since some CPUs may not be
+	 * available on the system.
+	 */
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (!CPU_ISSET(i, ctx->cpuset) && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			rte_log(RTE_LOG_DEBUG, threads_logtype_test, "CPU %zu should not be set for this thread!\n",
+					i);
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize thread attributes!");
+
+	CPU_ZERO(&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
+	RTE_TEST_ASSERT(ret == 0, "Failed to get main thread affinity!");
+
+	ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread attributes!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].cpuset = &cpuset;
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity, &ctx[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(ctx[i].result, 0, "Unexpected thread affinity!");
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_priority(void *arg)
+{
+	int ret;
+	enum rte_thread_priority priority;
+	int *result = arg;
+
+	*result = 1;
+	ret = rte_thread_get_priority(rte_thread_self(), &priority);
+	if (ret != 0 || priority != RTE_THREAD_PRIORITY_NORMAL)
+		*result = 2;
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	int ret = 0;
+	int results[THREADS_COUNT] = {};
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize  thread attributes!");
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread priority!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_priority, &results[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(results[i], 1, "Unexpected priority value!");
+	}
+
+	return ret;
+}
+
 static struct unit_test_suite threads_test_suite = {
 	.suite_name = "threads autotest",
 	.setup = NULL,
 	.teardown = NULL,
 	.unit_test_cases = {
 			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
 			TEST_CASES_END()
 	}
 };
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 09/13] app/test: add unit tests for thread lifetime management
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (7 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 08/13] app/test: add unit tests for thread attributes Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 10/13] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
                                                           ` (5 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Verify that threads are created and cleaned up correctly.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/test_threads.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/app/test/test_threads.c b/app/test/test_threads.c
index 53e5892793..9fcae34179 100644
--- a/app/test/test_threads.c
+++ b/app/test/test_threads.c
@@ -167,6 +167,34 @@ test_thread_attributes_priority(void)
 	return ret;
 }
 
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_detach(threads_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to detach thread!");
+	}
+
+	return ret;
+}
+
 static struct unit_test_suite threads_test_suite = {
 	.suite_name = "threads autotest",
 	.setup = NULL,
@@ -175,6 +203,7 @@ static struct unit_test_suite threads_test_suite = {
 			TEST_CASE(test_thread_self),
 			TEST_CASE(test_thread_attributes_affinity),
 			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
 			TEST_CASES_END()
 	}
 };
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 10/13] eal: implement functions for thread barrier management
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (8 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 09/13] app/test: add unit tests for thread lifetime management Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 11/13] app/test: add unit tests for barrier Narcisa Ana Maria Vasile
                                                           ` (4 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index b3a9d4b47e..30e2ca79d1 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -295,6 +295,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index e841321819..7c84e32988 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,18 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -302,6 +314,52 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 0384a09fa2..06e5f82da2 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -427,6 +427,9 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 669a68d6a8..3f72bbf716 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -504,6 +504,62 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 11/13] app/test: add unit tests for barrier
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (9 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 10/13] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 12/13] eal: implement functions for mutex management Narcisa Ana Maria Vasile
                                                           ` (3 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Verify that the barrier correctly synchronizes all threads.
Verify that the threads are unblocked after the required
number of threads have called barrier_wait().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/test_threads.c | 49 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/app/test/test_threads.c b/app/test/test_threads.c
index 9fcae34179..00f604ab7e 100644
--- a/app/test/test_threads.c
+++ b/app/test/test_threads.c
@@ -195,6 +195,54 @@ test_thread_detach(void)
 	return ret;
 }
 
+struct thread_context {
+	rte_thread_barrier *barrier;
+	int barrier_result;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+	struct thread_context *ctx = arg;
+
+	ctx->barrier_result = rte_thread_barrier_wait(ctx->barrier);
+	if (ctx->barrier_result > 0)
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to wait at barrier!");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t thread_id;
+	struct thread_context ctx;
+	rte_thread_barrier barrier;
+	int ret = 0;
+	int result = 0;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	ctx.barrier = &barrier;
+	ret = rte_thread_create(&thread_id, NULL, thread_loop_barrier, &ctx);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	result = rte_thread_barrier_wait(&barrier);
+	RTE_TEST_ASSERT(result <= 0, "Failed to wait at the barrier!");
+
+	ret = rte_thread_join(thread_id, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	RTE_TEST_ASSERT(ctx.barrier_result <= 0, "Child thread failed to wait at the barrier!");
+	RTE_TEST_ASSERT_NOT_EQUAL(ctx.barrier_result, result, "Threads were not blocked at the barrier!");
+
+	return 0;
+}
+
 static struct unit_test_suite threads_test_suite = {
 	.suite_name = "threads autotest",
 	.setup = NULL,
@@ -204,6 +252,7 @@ static struct unit_test_suite threads_test_suite = {
 			TEST_CASE(test_thread_attributes_affinity),
 			TEST_CASE(test_thread_attributes_priority),
 			TEST_CASE(test_thread_detach),
+			TEST_CASE(test_thread_barrier),
 			TEST_CASES_END()
 	}
 };
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 12/13] eal: implement functions for mutex management
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (10 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 11/13] app/test: add unit tests for barrier Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 13/13] app/test: add unit tests for mutex Narcisa Ana Maria Vasile
                                                           ` (2 subsequent siblings)
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock, trylock.

Windows does not have a static initializer. Initialization
is only done through InitializeCriticalSection(). To overcome this,
RTE_INIT_MUTEX macro is added to replace static initialization
of mutexes. The macro calls rte_thread_mutex_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 69 +++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 85 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  5 +++
 lib/eal/windows/rte_thread.c | 64 +++++++++++++++++++++++++++
 4 files changed, 223 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 30e2ca79d1..580448d8bf 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -295,6 +295,75 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_trylock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7c84e32988..09a5fd8add 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,25 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_INIT_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * Returned by rte_thread_barrier_wait() when call is successful.
  */
@@ -314,6 +333,72 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Tries to lock a mutex.If the mutex is already held by a different thread,
+ * the function returns without blocking.
+ *
+ * @param mutex
+ *    The mutex that will be acquired, if not already locked.
+ *
+ * @return
+ *   On success, if the mutex is acquired, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_try_lock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Initializes a synchronization barrier.
  *
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 06e5f82da2..e80eea4316 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -431,6 +431,11 @@ EXPERIMENTAL {
 	rte_thread_barrier_wait;
 	rte_thread_barrier_destroy;
 	rte_thread_get_affinity_by_id;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_try_lock;
+	rte_thread_mutex_destroy;
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
 	rte_thread_set_priority;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 3f72bbf716..11b4863fe8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -504,6 +504,70 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (TryEnterCriticalSection(mutex->mutex_id) != 0)
+		return 0;
+
+	return EBUSY;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [dpdk-dev] [PATCH v17 13/13] app/test: add unit tests for mutex
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (11 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 12/13] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-11-10  3:01                                         ` Narcisa Ana Maria Vasile
  2021-11-10  9:31                                         ` [dpdk-dev] [PATCH v17 00/13] eal: Add EAL API for threading Thomas Monjalon
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
  14 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:01 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

As a new API for threading is introduced,
a set of unit tests have been added to test the new interface.

Verify that the mutex correctly locks/unlocks and protects the data.
Check both static and dynamic mutexes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/test_threads.c | 106 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/app/test/test_threads.c b/app/test/test_threads.c
index 00f604ab7e..91155a04e3 100644
--- a/app/test/test_threads.c
+++ b/app/test/test_threads.c
@@ -243,6 +243,110 @@ test_thread_barrier(void)
 	return 0;
 }
 
+RTE_INIT_MUTEX(static_mutex);
+
+struct mutex_loop_args {
+	rte_thread_barrier *barrier;
+	rte_thread_mutex *mutex;
+	unsigned long result_A;
+	unsigned long result_B;
+};
+
+static void *
+thread_loop_mutex_B(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) == 0) {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_B = 1;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_B = 2;
+	}
+
+	return NULL;
+}
+
+static void *
+thread_loop_mutex_A(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) != 0) {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_A = 2;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_A = 1;
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(rte_thread_mutex *pmutex)
+{
+	rte_thread_t thread_A;
+	rte_thread_t thread_B;
+	rte_thread_mutex mutex;
+	rte_thread_barrier barrier;
+	struct mutex_loop_args args;
+	int ret = 0;
+
+	/* If mutex is not statically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_init(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to initialize mutex!");
+	} else
+		mutex = *pmutex;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	args.mutex = &mutex;
+	args.barrier = &barrier;
+
+	ret = rte_thread_create(&thread_A, NULL, thread_loop_mutex_A, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_create(&thread_B, NULL, thread_loop_mutex_B, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_join(thread_A, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	ret = rte_thread_join(thread_B, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	RTE_TEST_ASSERT(args.result_A != args.result_B, "Mutex failed to be acquired or was acquired by both threads!");
+
+	/* Destroy if dynamically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_destroy(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to destroy mutex!");
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	return ret;
+}
+
+static int
+test_thread_mutex_static(void)
+{
+	return test_thread_mutex(&static_mutex);
+}
+
+static int
+test_thread_mutex_dynamic(void)
+{
+	return test_thread_mutex(NULL);
+}
+
 static struct unit_test_suite threads_test_suite = {
 	.suite_name = "threads autotest",
 	.setup = NULL,
@@ -253,6 +357,8 @@ static struct unit_test_suite threads_test_suite = {
 			TEST_CASE(test_thread_attributes_priority),
 			TEST_CASE(test_thread_detach),
 			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex_static),
+			TEST_CASE(test_thread_mutex_dynamic),
 			TEST_CASES_END()
 	}
 };
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-11-09  8:27                                             ` Thomas Monjalon
@ 2021-11-10  3:04                                               ` Narcisa Ana Maria Vasile
  2021-11-10  3:59                                                 ` Stephen Hemminger
  0 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:04 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam, stephen

On Tue, Nov 09, 2021 at 09:27:09AM +0100, Thomas Monjalon wrote:
> 09/11/2021 02:59, Narcisa Ana Maria Vasile:
> > On Tue, Oct 12, 2021 at 06:12:21PM +0200, Thomas Monjalon wrote:
> > > 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > > > From: Narcisa Vasile <navasile@microsoft.com>
> > > > 
> > > > Implement thread attributes for:
> > > > * thread affinity
> > > > * thread priority
> > > > Implement functions for managing thread attributes.
> > > > 
> > > > Priority is represented through an enum that allows for two levels:
> > > > 	- RTE_THREAD_PRIORITY_NORMAL
> > > > 	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
> > > 
> > > It doesn't say how do you translate these priorites in POSIX and win32.
> > 
> >   I'll send a new version with a better commit message.
> >   Thread priorities on both Linux-based and Windows platforms are similarly
> >   constructed from a class/policy + priority value. Currently in DPDK, most threads
> >   operate at the OS-default priority level but there are cases when increasing the
> >   priority is useful. For example, the Mellanox data path acceleration driver requires
> >   realtime thread priority. Similarly, some Windows applications will require elevated
> >   priority.
> 
> It should not. We should not use realtime priority.

Thomas, can you join the community sync tomorrow? I'll bring this up to discuss.

High performance applications benefit from an option to raise the priority of their threads
to avoid being preemted by other threads on the system. If there are issues with realtime
priority on some of the platforms, maybe we can add a warning for the user to make them
aware of possible crashes as Stephen H. suggested some time ago. Note that this patch doesn't
change the priority of EAL threads, enabling the higher priority will be done through a command
line option when starting the application.
Maybe we can explore raising the priority but not to the realtime level.

> 
> >   For these reasons, EAL will advertise 2 priority levels which are named suggestively
> >   "normal" and "realtime_critical" and are computed as follows:
> > 
> >   For Linux and similar platforms:
> >     * EAL "normal" priority corresponds to the (default) SCHED_OTHER policy + a priority value of
> >       (sched_get_priority_min(SCHED_OTHER) + sched_get_priority_max(SCHED_OTHER))/2.
> >       Note that on Linux the resulting priority value will be 0,
> >       in accordance to the docs guidance that mention the value should be 0 for SCHED_OTHER policy.
> > 	
> >     * EAL "realtime" priority corresponds to the SCHED_RR policy + a priority value of 
> >       sched_get_priority_max(SCHED_RR);
> > 
> >   For Windows:
> >     * EAL "normal" corresponds to class NORMAL_PRIORITY_CLASS +
> >       priority THREAD_PRIORITY_NORMAL
> >     * EAL "realtime_critical" corresponds to class REALTIME_PRIORITY_CLASS +
> >       priority THREAD_PRIORITY_TIME_CRITICAL
> 
> 

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API
  2021-11-09  8:32                                             ` Thomas Monjalon
@ 2021-11-10  3:07                                               ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:07 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Tue, Nov 09, 2021 at 09:32:08AM +0100, Thomas Monjalon wrote:
> 09/11/2021 03:10, Narcisa Ana Maria Vasile:
> > On Tue, Oct 12, 2021 at 06:33:16PM +0200, Thomas Monjalon wrote:
> > > 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > > > From: Narcisa Vasile <navasile@microsoft.com>
> > > > 
> > > > As a new API for threading is introduced,
> > > > a set of unit tests have been added to test the new interface.
> > > > The tests verify that:
> > > >  * mutexes and barriers behave as expected
> > > >  * thread properties are applied correctly
> > > >  * the thread id is retrieved correctly
> > > >  * thread creation/destruction works properly
> > > 
> > > Please make each test part of the patch implementing the feature.
> > > Thanks
> > > 
> > Makes sense, but most of these unit tests use rte_thread_create and
> > rte_thread_join to handle the creation and cleanup of the threads
> > that are being tested, so I'm forced to have this test patch at the end.
> 
> You mean you cannot start the series with implementing these 2 functions?

  Yes, rte_thread_create() depends on thread attributes. However, some of the
  other components can still be tested separately. I've broken it down in v17
  to allow for better progressive testing, but the first 3 tests follow after the
  first 3 features.
> 
> > I could still break it up into smaller patches, one for each test category
> > (mutex, attributes, etc) if you want. 
> 
> I would like to see features built & tested atomically and progressively.
> 


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management
  2021-11-09  2:07                                           ` Narcisa Ana Maria Vasile
@ 2021-11-10  3:13                                             ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-10  3:13 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, dmitry.kozliuk, khot, dmitrym, roretzla, talshn, ocardona,
	bruce.richardson, david.marchand, pallavi.kadam

On Mon, Nov 08, 2021 at 06:07:34PM -0800, Narcisa Ana Maria Vasile wrote:
> On Tue, Oct 12, 2021 at 06:32:09PM +0200, Thomas Monjalon wrote:
> > 09/10/2021 09:41, Narcisa Ana Maria Vasile:
> > > From: Narcisa Vasile <navasile@microsoft.com>
> > > 
> > > Add functions for barrier init, destroy, wait.
> > > 
> > > A portable type is used to represent a barrier identifier.
> > > The rte_thread_barrier_wait() function returns the same value
> > > on all platforms.
> > > 
> > > Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> > > ---
> > >  lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
> > >  lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
> > >  lib/eal/version.map          |  3 ++
> > >  lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
> > >  4 files changed, 178 insertions(+)
> > 
> > It doesn't need to be part of the API.
> > The pthread barrier is used only as part of the control thread implementation.
> > The need disappear if you implement control thread on Windows.
> > 
> Actually I think I have the implementation already. I've worked at this some time ago,
> I have this patch:
> [v4,2/6] eal: add function for control thread creation
> 
> The issue is I will break ABI so I cannot merge it as part of this patchset.
> I'll see if I can remove this barrier patch though.

  I couldn't find a good way to test mutexes without barriers, so I kept this for now.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-11-10  3:04                                               ` Narcisa Ana Maria Vasile
@ 2021-11-10  3:59                                                 ` Stephen Hemminger
  2021-11-10  4:20                                                   ` [EXTERNAL] " Tyler Retzlaff
  0 siblings, 1 reply; 290+ messages in thread
From: Stephen Hemminger @ 2021-11-10  3:59 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: Thomas Monjalon, dev, dmitry.kozliuk, khot, dmitrym, roretzla,
	talshn, ocardona, bruce.richardson, david.marchand,
	pallavi.kadam

On Tue, 9 Nov 2021 19:04:17 -0800
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> > >   I'll send a new version with a better commit message.
> > >   Thread priorities on both Linux-based and Windows platforms are similarly
> > >   constructed from a class/policy + priority value. Currently in DPDK, most threads
> > >   operate at the OS-default priority level but there are cases when increasing the
> > >   priority is useful. For example, the Mellanox data path acceleration driver requires
> > >   realtime thread priority. Similarly, some Windows applications will require elevated
> > >   priority.  
> > 
> > It should not. We should not use realtime priority.  
> 
> Thomas, can you join the community sync tomorrow? I'll bring this up to discuss.
> 
> High performance applications benefit from an option to raise the priority of their threads
> to avoid being preemted by other threads on the system. If there are issues with realtime
> priority on some of the platforms, maybe we can add a warning for the user to make them
> aware of possible crashes as Stephen H. suggested some time ago. Note that this patch doesn't
> change the priority of EAL threads, enabling the higher priority will be done through a command
> line option when starting the application.
> Maybe we can explore raising the priority but not to the realtime level.

Let me put it more succulently.
Almost all DPDK applications have threads that are a 100% CPU doing polling.
Putting those thread as real-time thread breaks Linux badly because the kernel
can and will try and run work on those CPU's and the system is broken/unstable/dead
at that point.

This is a case of different definitions and expectations of real-time in
Linux and Windows.  Linux definition of real-time priority is for well behaved
and time critical applications. It expects RT applications to run, then sleep.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* RE: [EXTERNAL] Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-11-10  3:59                                                 ` Stephen Hemminger
@ 2021-11-10  4:20                                                   ` Tyler Retzlaff
  2021-11-10  6:29                                                     ` [dpdk-dev] [EXTERNAL] " Stephen Hemminger
  0 siblings, 1 reply; 290+ messages in thread
From: Tyler Retzlaff @ 2021-11-10  4:20 UTC (permalink / raw)
  To: Stephen Hemminger, Narcisa Ana Maria Vasile
  Cc: thomas, dev, Dmitry Kozlyuk, Khoa To, Dmitry Malloy, talshn,
	Omar Cardona, bruce.richardson, david.marchand, Kadam, Pallavi



-----Original Message-----
From: Stephen Hemminger <stephen@networkplumber.org> 
Sent: Tuesday, November 9, 2021 8:00 PM
To: Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>
Cc: thomas <thomas@monjalon.net>; dev@dpdk.org; Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>; Khoa To <khot@microsoft.com>; Dmitry Malloy <dmitrym@microsoft.com>; Tyler Retzlaff <roretzla@microsoft.com>; talshn <talshn@mellanox.com>; Omar Cardona <ocardona@microsoft.com>; bruce.richardson@intel.com; david.marchand@redhat.com; Kadam, Pallavi <pallavi.kadam@intel.com>
Subject: [EXTERNAL] Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes

On Tue, 9 Nov 2021 19:04:17 -0800
Narcisa Ana Maria Vasile <navasile@linux.microsoft.com> wrote:

> > > >   I'll send a new version with a better commit message.
> > > >   Thread priorities on both Linux-based and Windows platforms are similarly
> > > >   constructed from a class/policy + priority value. Currently in DPDK, most threads
> > > >   operate at the OS-default priority level but there are cases when increasing the
> > > >   priority is useful. For example, the Mellanox data path acceleration driver requires
> > > >   realtime thread priority. Similarly, some Windows applications will require elevated
> > > >   priority.  
> > > 
> > >  It should not. We should not use realtime priority.  
> >
> > Thomas, can you join the community sync tomorrow? I'll bring this up to discuss.
> >
> > High performance applications benefit from an option to raise the 
> > priority of their threads to avoid being preemted by other threads on 
> > the system. If there are issues with realtime priority on some of the 
> > platforms, maybe we can add a warning for the user to make them aware 
> > of possible crashes as Stephen H. suggested some time ago. Note that 
> > this patch doesn't change the priority of EAL threads, enabling the higher priority will be done through a command line option when starting the application.
> > Maybe we can explore raising the priority but not to the realtime level.

> Let me put it more succulently.
> Almost all DPDK applications have threads that are a 100% CPU doing polling.
> Putting those thread as real-time thread breaks Linux badly because the kernel can and will try and run work on those CPU's and the system is broken/unstable/dead at that point.

The suggestion is that when running on Windows it should be possible for the application to be configured to use real-time threads, there is no implication that it will force real-time priority on Linux.  If it doesn't make sense for it to be configured on Linux then don't configure it.  But saying it shall not be configurable for any platform just because one platform can't make use of the configuration and those platforms have to run compromised makes little sense.  Linux administrators are (or should be) knowledgeable enough to know what configuration to use.

> > This is a case of different definitions and expectations of real-time in Linux and Windows.  Linux definition of real-time priority is for well behaved and time critical applications. It expects RT applications to run, then sleep.

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v16 2/9] eal: add thread attributes
  2021-11-10  4:20                                                   ` [EXTERNAL] " Tyler Retzlaff
@ 2021-11-10  6:29                                                     ` Stephen Hemminger
  2021-11-10  9:21                                                       ` Bruce Richardson
  0 siblings, 1 reply; 290+ messages in thread
From: Stephen Hemminger @ 2021-11-10  6:29 UTC (permalink / raw)
  To: Tyler Retzlaff
  Cc: Narcisa Ana Maria Vasile, thomas, dev, Dmitry Kozlyuk, Khoa To,
	Dmitry Malloy, talshn, Omar Cardona, bruce.richardson,
	david.marchand, Kadam, Pallavi

On Wed, 10 Nov 2021 04:20:52 +0000
Tyler Retzlaff <roretzla@microsoft.com> wrote:

> > >
> > > High performance applications benefit from an option to raise the 
> > > priority of their threads to avoid being preemted by other threads on 
> > > the system. If there are issues with realtime priority on some of the 
> > > platforms, maybe we can add a warning for the user to make them aware 
> > > of possible crashes as Stephen H. suggested some time ago. Note that 
> > > this patch doesn't change the priority of EAL threads, enabling the higher priority will be done through a command line option when starting the application.
> > > Maybe we can explore raising the priority but not to the realtime level.  
> 
> > Let me put it more succulently.
> > Almost all DPDK applications have threads that are a 100% CPU doing polling.
> > Putting those thread as real-time thread breaks Linux badly because the kernel can and will try and run work on those CPU's and the system is broken/unstable/dead at that point.  
> 
> The suggestion is that when running on Windows it should be possible for the application to be configured to use real-time threads, there is no implication that it will force real-time priority on Linux.  If it doesn't make sense for it to be configured on Linux then don't configure it.  But saying it shall not be configurable for any platform just because one platform can't make use of the configuration and those platforms have to run compromised makes little sense.  Linux administrators are (or should be) knowledgeable enough to know what configuration to use.
>

Why not just make it always return an error when real-time is requested on Linux from a DPDK thread.

The experience on the mailing list is that users will find trouble.
Maybe it is just that the sampling is biased. Users that are knowledgeable or figure out
problems themselves don't come to the mailing list.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [EXTERNAL] Re: [PATCH v16 2/9] eal: add thread attributes
  2021-11-10  6:29                                                     ` [dpdk-dev] [EXTERNAL] " Stephen Hemminger
@ 2021-11-10  9:21                                                       ` Bruce Richardson
  2021-11-10 16:52                                                         ` [EXTERNAL] Re: [dpdk-dev] " Tyler Retzlaff
  0 siblings, 1 reply; 290+ messages in thread
From: Bruce Richardson @ 2021-11-10  9:21 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Tyler Retzlaff, Narcisa Ana Maria Vasile, thomas, dev,
	Dmitry Kozlyuk, Khoa To, Dmitry Malloy, talshn, Omar Cardona,
	david.marchand, Kadam, Pallavi

On Tue, Nov 09, 2021 at 10:29:25PM -0800, Stephen Hemminger wrote:
> On Wed, 10 Nov 2021 04:20:52 +0000
> Tyler Retzlaff <roretzla@microsoft.com> wrote:
> 
> > > >
> > > > High performance applications benefit from an option to raise the 
> > > > priority of their threads to avoid being preemted by other threads on 
> > > > the system. If there are issues with realtime priority on some of the 
> > > > platforms, maybe we can add a warning for the user to make them aware 
> > > > of possible crashes as Stephen H. suggested some time ago. Note that 
> > > > this patch doesn't change the priority of EAL threads, enabling the higher priority will be done through a command line option when starting the application.
> > > > Maybe we can explore raising the priority but not to the realtime level.  
> > 
> > > Let me put it more succulently.
> > > Almost all DPDK applications have threads that are a 100% CPU doing polling.
> > > Putting those thread as real-time thread breaks Linux badly because the kernel can and will try and run work on those CPU's and the system is broken/unstable/dead at that point.  
> > 
> > The suggestion is that when running on Windows it should be possible for the application to be configured to use real-time threads, there is no implication that it will force real-time priority on Linux.  If it doesn't make sense for it to be configured on Linux then don't configure it.  But saying it shall not be configurable for any platform just because one platform can't make use of the configuration and those platforms have to run compromised makes little sense.  Linux administrators are (or should be) knowledgeable enough to know what configuration to use.
> >
> 
> Why not just make it always return an error when real-time is requested on Linux from a DPDK thread.
>
I would tend to agree with this suggestion, that we just return ENOTSUP
error code for Linux. It's too easy to lock up a linux system with realtime
DPDK threads. If a user really knows what they are doing and they need
realtime priority on linux, they can use the linux scheduler APIs directly.
However, I am ok with having such a function supported on Windows if it's
needed. Unfortunately, I don't know for sure about BSD, but it probably
should follow the linux approach initially unless proved safe.

/Bruce

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [dpdk-dev] [PATCH v17 00/13]  eal: Add EAL API for threading
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (12 preceding siblings ...)
  2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 13/13] app/test: add unit tests for mutex Narcisa Ana Maria Vasile
@ 2021-11-10  9:31                                         ` Thomas Monjalon
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
  14 siblings, 0 replies; 290+ messages in thread
From: Thomas Monjalon @ 2021-11-10  9:31 UTC (permalink / raw)
  To: Narcisa Ana Maria Vasile
  Cc: dev, dmitry.kozliuk, khot, navasile, dmitrym, roretzla, talshn,
	ocardona, bruce.richardson, david.marchand, pallavi.kadam

10/11/2021 04:01, Narcisa Ana Maria Vasile:
> Narcisa Vasile (13):
>   eal: add basic threading functions
>   eal: add thread attributes
>   eal/windows: translate Windows errors to errno-style errors
>   eal: implement functions for thread affinity management
>   eal: implement thread priority management functions
>   eal: add thread lifetime management
>   app/test: add unit tests for rte_thread_self
>   app/test: add unit tests for thread attributes
>   app/test: add unit tests for thread lifetime management
>   eal: implement functions for thread barrier management
>   app/test: add unit tests for barrier
>   eal: implement functions for mutex management
>   app/test: add unit tests for mutex

I see there was a misunderstanding in the patch organization.
I was asking for test being done progressively and atomically
when features are introduced. By "atomically" I mean that
the test patches can be squashed with the relevant feature patch.
Example: test mutex patch should be squashed in EAL mutex patch.
Thanks



^ permalink raw reply	[flat|nested] 290+ messages in thread

* RE: [EXTERNAL] Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes
  2021-11-10  9:21                                                       ` Bruce Richardson
@ 2021-11-10 16:52                                                         ` Tyler Retzlaff
  0 siblings, 0 replies; 290+ messages in thread
From: Tyler Retzlaff @ 2021-11-10 16:52 UTC (permalink / raw)
  To: Bruce Richardson, Stephen Hemminger
  Cc: Narcisa Ana Maria Vasile, thomas, dev, Dmitry Kozlyuk, Khoa To,
	Dmitry Malloy, talshn, Omar Cardona, david.marchand, Kadam,
	Pallavi



-----Original Message-----
From: Bruce Richardson <bruce.richardson@intel.com> 
Sent: Wednesday, November 10, 2021 1:21 AM
To: Stephen Hemminger <stephen@networkplumber.org>
Cc: Tyler Retzlaff <roretzla@microsoft.com>; Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>; thomas <thomas@monjalon.net>; dev@dpdk.org; Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>; Khoa To <khot@microsoft.com>; Dmitry Malloy <dmitrym@microsoft.com>; talshn <talshn@mellanox.com>; Omar Cardona <ocardona@microsoft.com>; david.marchand@redhat.com; Kadam, Pallavi <pallavi.kadam@intel.com>
Subject: Re: [EXTERNAL] Re: [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes

> On Tue, Nov 09, 2021 at 10:29:25PM -0800, Stephen Hemminger wrote:
> > On Wed, 10 Nov 2021 04:20:52 +0000
> > Tyler Retzlaff <roretzla@microsoft.com> wrote:
> > 
> > > > >
> > > > > High performance applications benefit from an option to raise 
> > > > > the priority of their threads to avoid being preemted by other 
> > > > > threads on the system. If there are issues with realtime 
> > > > > priority on some of the platforms, maybe we can add a warning 
> > > > > for the user to make them aware of possible crashes as Stephen 
> > > > > H. suggested some time ago. Note that this patch doesn't change the priority of EAL threads, enabling the higher priority will be done through a command line option when starting the application.
> > > > > Maybe we can explore raising the priority but not to the realtime level.  
> > > 
> > > > Let me put it more succulently.
> > > > Almost all DPDK applications have threads that are a 100% CPU doing polling.
> > > > Putting those thread as real-time thread breaks Linux badly because the kernel can and will try and run work on those CPU's and the system is broken/unstable/dead at that point.  
> > > 
> > > The suggestion is that when running on Windows it should be possible for the application to be configured to use real-time threads, there is no implication that it will force real-time priority on Linux.  If it doesn't make sense for it to be configured on Linux then don't configure it.  But saying it shall not be configurable for any platform just because one platform can't make use of the configuration and those platforms have to run compromised makes little sense.  Linux administrators are (or should be) knowledgeable enough to know what configuration to use.
> > >
> > 
> > Why not just make it always return an error when real-time is requested on Linux from a DPDK thread.
> >
> I would tend to agree with this suggestion, that we just return ENOTSUP error code for Linux. It's too easy to lock up a linux system with realtime DPDK threads. If a user really knows what they are doing and they need realtime priority on linux, they can use the linux scheduler APIs directly.

This sounds reasonable to me.  It doesn't compromise the Linux platform and allows the Windows platform to reach potential.

> However, I am ok with having such a function supported on Windows if it's needed. Unfortunately, I don't know for sure about BSD, but it probably should follow the linux approach initially unless proved safe.

Agreed, probably true for all POSIX platforms that support RT extensions.


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 0/8]   eal: Add EAL API for threading
  2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
                                                           ` (13 preceding siblings ...)
  2021-11-10  9:31                                         ` [dpdk-dev] [PATCH v17 00/13] eal: Add EAL API for threading Thomas Monjalon
@ 2021-11-11  1:33                                         ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 1/8] eal: add basic threading functions Narcisa Ana Maria Vasile
                                                             ` (7 more replies)
  14 siblings, 8 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

EAL thread API

**Problem Statement**
DPDK currently uses the pthread interface to create and manage threads.
Windows does not support the POSIX thread programming model,
so it currently
relies on a header file that hides the Windows calls under
pthread matched interfaces. Given that EAL should isolate the environment
specifics from the applications and libraries and mediate
all the communication with the operating systems, a new EAL interface
is needed for thread management.

**Goals**
* Introduce a generic EAL API for threading support that will remove
  the current Windows pthread.h shim.
* Replace references to pthread_* across the DPDK codebase with the new
  RTE_THREAD_* API.
* Allow users to choose between using the RTE_THREAD_* API or a
  3rd party thread library through a configuration option.

**Design plan**
New API main files:
* rte_thread.h (librte_eal/include)
* rte_thread.c (librte_eal/windows)
* rte_thread.c (librte_eal/common)

**A schematic example of the design**
--------------------------------------------------
lib/librte_eal/include/rte_thread.h
int rte_thread_create();

lib/librte_eal/common/rte_thread.c
int rte_thread_create() 
{
	return pthread_create();
}

lib/librte_eal/windows/rte_thread.c
int rte_thread_create() 
{
	return CreateThread();
}
-----------------------------------------------------

**Thread attributes**

When or after a thread is created, specific characteristics of the thread
can be adjusted. Currently in DPDK most threads operate at the OS-default
priority level but there are cases when increasing the priority is useful.
For example, high-performance applications require elevated priority to
avoid being preempted by other threads on the system.
The following structure that represents thread attributes has been
defined:

typedef struct
{
	enum rte_thread_priority priority;
	rte_cpuset_t cpuset;
} rte_thread_attr_t;

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t
object that will cause the thread to be created with the
affinity and priority
described by the attributes object. If no rte_thread_attr_t is passed
(parameter is NULL), the default affinity and priority are used.
An rte_thread_attr_t object can also be set to the default values
by calling *rte_thread_attr_init()*.

*Priority* is represented through an enum that currently advertises
two values for priority:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL
The enum can be extended to allow for multiple priority levels.
rte_thread_set_priority      - sets the priority of a thread
rte_thread_get_priority      - retrieves the priority of a thread
                               from the OS
rte_thread_attr_set_priority - updates an rte_thread_attr_t object
                               with a new value for priority

*Affinity* is described by the already known “rte_cpuset_t” type.
rte_thread_attr_set/get_affinity - sets/gets the affinity field in a
                                   rte_thread_attr_t object
rte_thread_set/get_affinity      – sets/gets the affinity of a thread

**Errors**
As different platforms have different error codes, the approach here
is to translate the Windows error to POSIX-style ones to have
uniformity over the values returned. 

**Future work**
The long term plan is for EAL to provide full threading support:
* Add support for conditional variables
* Additional functionality offered by pthread_*
  (such as pthread_setname_np, etc.)

v18:
 - Squash unit tests in corresponding patches.
 - Prevent priority to be set to realtime on non-Windows systems.
 - Use already existing affinity function in rte_thread_create()

v17:
 - Move unrelated changes to the correct patch.
 - Rename RTE_STATIC_MUTEX to avoid confusion, since
   the mutex is still dynamically initialized behind the scenes.
 - Break down the unit tests into smaller patches and reorder them.
 - Remove duplicated code in header
 - Improve commit messages and cover letter.

v16:
- Fix warning on freebsd by adding cast
- Change affinity unit test to consider ases when the requested CPU
  are not available on the system.
- Fix priority unit test to avoid termination of thread before the
  priority is checked.

v15:
- Add try_lock mutex functionality. If the mutex is already owned by a
  different thread, the function returns immediately. Otherwise, 
  the mutex will be acquired.
- Add function for getting the priority of a thread.
  An auxiliary function that translates the OS priority to the
  EAL accepted ones is added.
- Fix unit tests logging, add descriptive asserts that mark test failures.
  Verify mutex locking, verify barrier return values. Add test for
  statically initialized mutexes.
- Fix Alpine build by removing the use of pthread_attr_set_affinity() and
  using pthread_set_affinity() after the thread is created.

v14:
- Remove patch "eal: add EAL argument for setting thread priority"
  This will be added later when enabling the new threading API.
- Remove priority enum value "_UNDEFINED". NORMAL is used
  as the default.
- Fix issue with thread return value.

v13:
 - Fix syntax error in unit tests

v12:
 - Fix freebsd warning about initializer in unit tests

v11:
 - Add unit tests for thread API
 - Rebase

v10:
 - Remove patch no. 10. It will be broken down in subpatches 
   and sent as a different patchset that depends on this one.
   This is done due to the ABI breaks that would be caused by patch 10.
 - Replace unix/rte_thread.c with common/rte_thread.c
 - Remove initializations that may prevent compiler from issuing useful
   warnings.
 - Remove rte_thread_types.h and rte_windows_thread_types.h
 - Remove unneeded priority macros (EAL_THREAD_PRIORITY*)
 - Remove functions that retrieves thread handle from process handle
 - Remove rte_thread_cancel() until same behavior is obtained on
   all platforms.
 - Fix rte_thread_detach() function description,
   return value and remove empty line.
 - Reimplement mutex functions. Add compatible representation for mutex
   identifier. Add macro to replace static mutex initialization instances.
 - Fix commit messages (lines too long, remove unicode symbols)

v9:
- Sign patches

v8:
- Rebase
- Add rte_thread_detach() API
- Set default priority, when user did not specify a value

v7:
Based on DmitryK's review:
- Change thread id representation
- Change mutex id representation
- Implement static mutex inititalizer for Windows
- Change barrier identifier representation
- Improve commit messages
- Add missing doxygen comments
- Split error translation function
- Improve name for affinity function
- Remove cpuset_size parameter
- Fix eal_create_cpu_map function
- Map EAL priority values to OS specific values
- Add thread wrapper for start routine
- Do not export rte_thread_cancel() on Windows
- Cleanup, fix comments, fix typos.

v6:
- improve error-translation function
- call the error translation function in rte_thread_value_get()

v5:
- update cover letter with more details on the priority argument

v4:
- fix function description
- rebase

v3:
- rebase

v2:
- revert changes that break ABI 
- break up changes into smaller patches
- fix coding style issues
- fix issues with errors
- fix parameter type in examples/kni.c

Narcisa Vasile (8):
  eal: add basic threading functions
  eal: add thread attributes
  eal/windows: translate Windows errors to errno-style errors
  eal: implement functions for thread affinity management
  eal: implement thread priority management functions
  eal: add thread lifetime management
  eal: implement functions for thread barrier management
  eal: implement functions for mutex management

 app/test/meson.build            |   2 +
 app/test/test_threads.c         | 372 ++++++++++++++++++
 lib/eal/common/meson.build      |   1 +
 lib/eal/common/rte_thread.c     | 511 +++++++++++++++++++++++++
 lib/eal/include/rte_thread.h    | 412 +++++++++++++++++++-
 lib/eal/unix/meson.build        |   1 -
 lib/eal/unix/rte_thread.c       |  92 -----
 lib/eal/version.map             |  22 ++
 lib/eal/windows/eal_lcore.c     | 176 ++++++---
 lib/eal/windows/eal_windows.h   |  10 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 656 ++++++++++++++++++++++++++++++--
 12 files changed, 2084 insertions(+), 173 deletions(-)
 create mode 100644 app/test/test_threads.c
 create mode 100644 lib/eal/common/rte_thread.c
 delete mode 100644 lib/eal/unix/rte_thread.c

-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 1/8] eal: add basic threading functions
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2022-04-12 18:00                                             ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 2/8] eal: add thread attributes Narcisa Ana Maria Vasile
                                                             ` (6 subsequent siblings)
  7 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Use a portable, type-safe representation for the thread identifier.
Add functions for comparing thread ids and obtaining the thread id
for the current thread.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/meson.build            |  1 +
 lib/eal/{unix => common}/rte_thread.c | 57 ++++++++++++++++----------
 lib/eal/include/rte_thread.h          | 53 ++++++++++++++++++------
 lib/eal/unix/meson.build              |  1 -
 lib/eal/version.map                   |  3 ++
 lib/eal/windows/rte_thread.c          | 58 +++++++++++++++++----------
 6 files changed, 117 insertions(+), 56 deletions(-)
 rename lib/eal/{unix => common}/rte_thread.c (66%)

diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index 917758cc65..6bdc9cd854 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -52,5 +52,6 @@ if not is_windows
             'hotplug_mp.c',
             'malloc_mp.c',
             'rte_keepalive.c',
+            'rte_thread.c'
     )
 endif
diff --git a/lib/eal/unix/rte_thread.c b/lib/eal/common/rte_thread.c
similarity index 66%
rename from lib/eal/unix/rte_thread.c
rename to lib/eal/common/rte_thread.c
index c72d619ec1..92a7451b0a 100644
--- a/lib/eal/unix/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <errno.h>
@@ -16,25 +17,41 @@ struct eal_tls_key {
 	pthread_key_t thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = (uintptr_t)pthread_self();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
 	int err;
+	rte_thread_key k;
 
-	*key = malloc(sizeof(**key));
-	if ((*key) == NULL) {
+	k = malloc(sizeof(*k));
+	if (k == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return EINVAL;
 	}
-	err = pthread_key_create(&((*key)->thread_index), destructor);
-	if (err) {
+	err = pthread_key_create(&(k->thread_index), destructor);
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
 			 strerror(err));
-		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		free(k);
+		return err;
 	}
+	*key = k;
 	return 0;
 }
 
@@ -43,18 +60,16 @@ rte_thread_key_delete(rte_thread_key key)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_key_delete(key->thread_index);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
 			 strerror(err));
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	free(key);
 	return 0;
@@ -65,17 +80,15 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	int err;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	err = pthread_setspecific(key->thread_index, value);
-	if (err) {
+	if (err != 0) {
 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
 			strerror(err));
-		rte_errno = ENOEXEC;
-		return -1;
+		return err;
 	}
 	return 0;
 }
@@ -83,7 +96,7 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 void *
 rte_thread_value_get(rte_thread_key key)
 {
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8be8ed8f36..c9cdeb07aa 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
+#include <stdint.h>
 
 #include <rte_os.h>
 #include <rte_compat.h>
@@ -20,11 +22,45 @@
 extern "C" {
 #endif
 
+#include <sched.h>
+
+/**
+ * Thread id descriptor.
+ */
+typedef struct rte_thread_tag {
+	uintptr_t opaque_id; /**< thread identifier */
+} rte_thread_t;
+
 /**
  * TLS key type, an opaque pointer.
  */
 typedef struct eal_tls_key *rte_thread_key;
 
+/**
+ * Get the id of the calling thread.
+ *
+ * @return
+ *   Return the thread id of the calling thread.
+ */
+__rte_experimental
+rte_thread_t rte_thread_self(void);
+
+/**
+ * Check if 2 thread ids are equal.
+ *
+ * @param t1
+ *   First thread id.
+ *
+ * @param t2
+ *   Second thread id.
+ *
+ * @return
+ *   If the ids are equal, return nonzero.
+ *   Otherwise, return 0.
+ */
+__rte_experimental
+int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
+
 #ifdef RTE_HAS_CPUSET
 
 /**
@@ -63,9 +99,7 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: ENOMEM  - Memory allocation error.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 
 __rte_experimental
@@ -80,9 +114,7 @@ int rte_thread_key_create(rte_thread_key *key,
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_key_delete(rte_thread_key key);
@@ -97,9 +129,7 @@ int rte_thread_key_delete(rte_thread_key key);
  *
  * @return
  *   On success, zero.
- *   On failure, a negative number and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, return a positive errno-style error number.
  */
 __rte_experimental
 int rte_thread_value_set(rte_thread_key key, const void *value);
@@ -112,9 +142,8 @@ int rte_thread_value_set(rte_thread_key key, const void *value);
  *
  * @return
  *   On success, value data pointer (can also be NULL).
- *   On failure, NULL and an error number is set in rte_errno.
- *   rte_errno can be: EINVAL  - Invalid parameter passed.
- *                     ENOEXEC - Specific OS error.
+ *   On failure, NULL and a positive error number is set in rte_errno.
+ *
  */
 __rte_experimental
 void *rte_thread_value_get(rte_thread_key key);
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index e3ecd3e956..cb6d233721 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -6,5 +6,4 @@ sources += files(
         'eal_unix_memory.c',
         'eal_unix_timer.c',
         'eal_firmware.c',
-        'rte_thread.c',
 )
diff --git a/lib/eal/version.map b/lib/eal/version.map
index ab28c22791..24e9747795 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -420,6 +420,9 @@ EXPERIMENTAL {
 	rte_intr_instance_free;
 	rte_intr_type_get;
 	rte_intr_type_set;
+
+	rte_thread_self;
+	rte_thread_equal;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 667287c387..26c8dd4ebe 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2021 Mellanox Technologies, Ltd
+ * Copyright(c) 2021 Microsoft Corporation
  */
 
 #include <rte_common.h>
@@ -11,22 +12,38 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+rte_thread_t
+rte_thread_self(void)
+{
+	rte_thread_t thread_id;
+
+	thread_id.opaque_id = GetCurrentThreadId();
+
+	return thread_id;
+}
+
+int
+rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
+{
+	return t1.opaque_id == t2.opaque_id;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
 {
+	int ret;
+
 	*key = malloc(sizeof(**key));
 	if ((*key) == NULL) {
 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
-		rte_errno = ENOMEM;
-		return -1;
+		return ENOMEM;
 	}
 	(*key)->thread_index = TlsAlloc();
 	if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
-		RTE_LOG_WIN32_ERR("TlsAlloc()");
+		ret = thread_log_last_error("TlsAlloc()");
 		free(*key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	return 0;
 }
@@ -34,16 +51,16 @@ rte_thread_key_create(rte_thread_key *key,
 int
 rte_thread_key_delete(rte_thread_key key)
 {
-	if (!key) {
+	int ret;
+
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	if (!TlsFree(key->thread_index)) {
-		RTE_LOG_WIN32_ERR("TlsFree()");
+		ret = thread_log_last_error("TlsFree()");
 		free(key);
-		rte_errno = ENOEXEC;
-		return -1;
+		return ret;
 	}
 	free(key);
 	return 0;
@@ -54,17 +71,14 @@ rte_thread_value_set(rte_thread_key key, const void *value)
 {
 	char *p;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
-		rte_errno = EINVAL;
-		return -1;
+		return EINVAL;
 	}
 	/* discard const qualifier */
 	p = (char *) (uintptr_t) value;
 	if (!TlsSetValue(key->thread_index, p)) {
-		RTE_LOG_WIN32_ERR("TlsSetValue()");
-		rte_errno = ENOEXEC;
-		return -1;
+		return thread_log_last_error("TlsSetValue()");
 	}
 	return 0;
 }
@@ -73,16 +87,18 @@ void *
 rte_thread_value_get(rte_thread_key key)
 {
 	void *output;
+	DWORD ret = 0;
 
-	if (!key) {
+	if (key == NULL) {
 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
 		rte_errno = EINVAL;
 		return NULL;
 	}
 	output = TlsGetValue(key->thread_index);
-	if (GetLastError() != ERROR_SUCCESS) {
-		RTE_LOG_WIN32_ERR("TlsGetValue()");
-		rte_errno = ENOEXEC;
+	ret = GetLastError();
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: TlsGetValue()\n", ret);
+		rte_errno = thread_translate_win32_error(ret);
 		return NULL;
 	}
 	return output;
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 2/8] eal: add thread attributes
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 1/8] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 3/8] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
                                                             ` (5 subsequent siblings)
  7 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement thread attributes for:
* thread affinity
* thread priority
Implement functions for managing thread attributes.

Priority is represented through an enum that allows for two levels:
	- RTE_THREAD_PRIORITY_NORMAL
	- RTE_THREAD_PRIORITY_REALTIME_CRITICAL

Affinity is described by the rte_cpuset_t type.

An rte_thread_attr_t object can be set to the default values
by calling rte_thread_attr_init().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 46 ++++++++++++++++++
 lib/eal/include/rte_thread.h | 91 ++++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  4 ++
 lib/eal/windows/rte_thread.c | 44 +++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 92a7451b0a..27ad1c7eb0 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_thread.h>
@@ -33,6 +34,51 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	CPU_ZERO(&attr->cpuset);
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	RTE_VERIFY(cpuset != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index c9cdeb07aa..8a20215a94 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,28 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+/**
+ * Thread priority values.
+ */
+enum rte_thread_priority {
+	RTE_THREAD_PRIORITY_NORMAL            = 0,
+	/**< normal thread priority, the default */
+	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,
+	/**< highest thread priority allowed */
+};
+
+#ifdef RTE_HAS_CPUSET
+
+/**
+ * Representation for thread attributes.
+ */
+typedef struct {
+	enum rte_thread_priority priority; /**< thread priority */
+	rte_cpuset_t cpuset; /**< thread affinity */
+} rte_thread_attr_t;
+
+#endif /* RTE_HAS_CPUSET */
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -63,6 +85,75 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Initialize the attributes of a thread.
+ * These attributes can be passed to the rte_thread_create() function
+ * that will create a new thread and set its attributes according to attr.
+ *
+ * @param attr
+ *   Thread attributes to initialize.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_init(rte_thread_attr_t *attr);
+
+/**
+ * Set the CPU affinity value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which affinity will be updated.
+ *
+ * @param cpuset
+ *   Points to the value of the affinity to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Get the value of CPU affinity that is set in the thread attributes pointed
+ * to by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes from which affinity will be retrieved.
+ *
+ * @param cpuset
+ *   Pointer to the memory that will store the affinity.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset);
+
+/**
+ * Set the thread priority value in the thread attributes pointed to
+ * by 'thread_attr'.
+ *
+ * @param thread_attr
+ *   Points to the thread attributes in which priority will be updated.
+ *
+ * @param priority
+ *   Points to the value of the priority to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority);
+
 /**
  * Set core affinity of the current thread.
  * Support both EAL and non-EAL thread and update TLS.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 24e9747795..3fc33fcd70 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -423,6 +423,10 @@ EXPERIMENTAL {
 
 	rte_thread_self;
 	rte_thread_equal;
+	rte_thread_attr_init;
+	rte_thread_attr_get_affinity;
+	rte_thread_attr_set_affinity;
+	rte_thread_attr_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 26c8dd4ebe..f65919f46d 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -4,6 +4,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
 #include <rte_windows.h>
@@ -28,6 +29,49 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+int
+rte_thread_attr_init(rte_thread_attr_t *attr)
+{
+	RTE_VERIFY(attr != NULL);
+
+	attr->priority = RTE_THREAD_PRIORITY_NORMAL;
+	CPU_ZERO(&attr->cpuset);
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+	thread_attr->cpuset = *cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
+		rte_cpuset_t *cpuset)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	*cpuset = thread_attr->cpuset;
+
+	return 0;
+}
+
+int
+rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
+		enum rte_thread_priority priority)
+{
+	RTE_VERIFY(thread_attr != NULL);
+
+	thread_attr->priority = priority;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 3/8] eal/windows: translate Windows errors to errno-style errors
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 1/8] eal: add basic threading functions Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 2/8] eal: add thread attributes Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 4/8] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
                                                             ` (4 subsequent siblings)
  7 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add function to translate Windows error codes to
errno-style error codes. The possible return values are chosen
so that we have as much semantical compatibility between platforms as
possible.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/windows/rte_thread.c | 48 ++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index f65919f46d..c1ecfbd6ae 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -13,6 +13,54 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+/* Translates the most common error codes related to threads */
+static int
+thread_translate_win32_error(DWORD error)
+{
+	switch (error) {
+	case ERROR_SUCCESS:
+		return 0;
+
+	case ERROR_INVALID_PARAMETER:
+		return EINVAL;
+
+	case ERROR_INVALID_HANDLE:
+		return EFAULT;
+
+	case ERROR_NOT_ENOUGH_MEMORY:
+	/* FALLTHROUGH */
+	case ERROR_NO_SYSTEM_RESOURCES:
+		return ENOMEM;
+
+	case ERROR_PRIVILEGE_NOT_HELD:
+	/* FALLTHROUGH */
+	case ERROR_ACCESS_DENIED:
+		return EACCES;
+
+	case ERROR_ALREADY_EXISTS:
+		return EEXIST;
+
+	case ERROR_POSSIBLE_DEADLOCK:
+		return EDEADLK;
+
+	case ERROR_INVALID_FUNCTION:
+	/* FALLTHROUGH */
+	case ERROR_CALL_NOT_IMPLEMENTED:
+		return ENOSYS;
+	}
+
+	return EINVAL;
+}
+
+static int
+thread_log_last_error(const char *message)
+{
+	DWORD error = GetLastError();
+	RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
+
+	return thread_translate_win32_error(error);
+}
+
 rte_thread_t
 rte_thread_self(void)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 4/8] eal: implement functions for thread affinity management
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
                                                             ` (2 preceding siblings ...)
  2021-11-11  1:33                                           ` [PATCH v18 3/8] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 5/8] eal: implement thread priority management functions Narcisa Ana Maria Vasile
                                                             ` (3 subsequent siblings)
  7 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Implement functions for getting/setting thread affinity.
Threads can be pinned to specific cores by setting their
affinity attribute.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Signed-off-by: Dmitry Malloy <dmitrym@microsoft.com>
---
 lib/eal/common/rte_thread.c   |  16 ++++
 lib/eal/include/rte_thread.h  |  36 +++++++
 lib/eal/version.map           |   2 +
 lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------
 lib/eal/windows/eal_windows.h |  10 ++
 lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-
 6 files changed, 319 insertions(+), 46 deletions(-)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 27ad1c7eb0..73b7b3141c 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
 }
 
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
+		sizeof(*cpuset), cpuset);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 8a20215a94..5b100cafda 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -85,6 +85,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
 
 #ifdef RTE_HAS_CPUSET
 
+/**
+ * Set the affinity of thread 'thread_id' to the cpu set
+ * specified by 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set the affinity.
+ *
+ * @param cpuset
+ *   Pointer to CPU affinity to set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset);
+
+/**
+ * Get the affinity of thread 'thread_id' and store it
+ * in 'cpuset'.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get the affinity.
+ *
+ * @param cpuset
+ *   Pointer for storing the affinity value.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset);
+
 /**
  * Initialize the attributes of a thread.
  * These attributes can be passed to the rte_thread_create() function
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 3fc33fcd70..193a79a4d2 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -427,6 +427,8 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_get_affinity_by_id;
+	rte_thread_set_affinity_by_id;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index 476c2d2bdf..295af50698 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -2,7 +2,6 @@
  * Copyright(c) 2019 Intel Corporation
  */
 
-#include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -27,13 +26,15 @@ struct socket_map {
 };
 
 struct cpu_map {
-	unsigned int socket_count;
 	unsigned int lcore_count;
+	unsigned int socket_count;
+	unsigned int cpu_count;
 	struct lcore_map lcores[RTE_MAX_LCORE];
 	struct socket_map sockets[RTE_MAX_NUMA_NODES];
+	GROUP_AFFINITY cpus[CPU_SETSIZE];
 };
 
-static struct cpu_map cpu_map = { 0 };
+static struct cpu_map cpu_map;
 
 /* eal_create_cpu_map() is called before logging is initialized */
 static void
@@ -47,13 +48,118 @@ log_early(const char *format, ...)
 	va_end(va);
 }
 
+static int
+eal_query_group_affinity(void)
+{
+	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;
+	unsigned int *cpu_count = &cpu_map.cpu_count;
+	DWORD infos_size = 0;
+	int ret = 0;
+	USHORT group_count;
+	KAFFINITY affinity;
+	USHORT group_no;
+	unsigned int i;
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, NULL,
+					      &infos_size)) {
+		DWORD error = GetLastError();
+		if (error != ERROR_INSUFFICIENT_BUFFER) {
+			log_early("Cannot get group information size, "
+				  "error %lu\n", error);
+			rte_errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	infos = malloc(infos_size);
+	if (infos == NULL) {
+		log_early("Cannot allocate memory for NUMA node information\n");
+		rte_errno = ENOMEM;
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (!GetLogicalProcessorInformationEx(RelationGroup, infos,
+					      &infos_size)) {
+		log_early("Cannot get group information, error %lu\n",
+			  GetLastError());
+		rte_errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+	*cpu_count = 0;
+	group_count = infos->Group.ActiveGroupCount;
+	for (group_no = 0; group_no < group_count; group_no++) {
+
+		affinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;
+
+		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+			if ((affinity & ((KAFFINITY)1 << i)) == 0)
+				continue;
+			cpu_map.cpus[*cpu_count].Group = group_no;
+			cpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;
+			(*cpu_count)++;
+		}
+	}
+
+cleanup:
+	free(infos);
+	return ret;
+}
+
+static bool
+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
+{
+	const unsigned int node_id = info->NumaNode.NodeNumber;
+	const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+	struct lcore_map *lcore;
+	unsigned int socket_id;
+	unsigned int i;
+
+	/* NUMA node may be reported multiple times if it includes
+	 * cores from different processor groups, e. g. 80 cores
+	 * of a physical processor comprise one NUMA node, but two
+	 * processor groups, because group size is limited by 32/64.
+	 */
+	for (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {
+		if (cpu_map.sockets[socket_id].node_id == node_id)
+			break;
+	}
+
+	if (socket_id == cpu_map.socket_count) {
+		if (socket_id == RTE_DIM(cpu_map.sockets))
+			return true;
+
+		cpu_map.sockets[socket_id].node_id = node_id;
+		cpu_map.socket_count++;
+	}
+
+	for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+		if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+			continue;
+
+		if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+			return true;
+
+		lcore = &cpu_map.lcores[cpu_map.lcore_count];
+		lcore->socket_id = socket_id;
+		lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
+		cpu_map.lcore_count++;
+	}
+	return false;
+}
+
 int
 eal_create_cpu_map(void)
 {
 	SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
 	DWORD infos_size;
 	bool full = false;
+	int ret = 0;
 
+	infos = NULL;
 	infos_size = 0;
 	if (!GetLogicalProcessorInformationEx(
 			RelationNumaNode, NULL, &infos_size)) {
@@ -78,57 +184,29 @@ eal_create_cpu_map(void)
 		log_early("Cannot get NUMA node information, error %lu\n",
 			GetLastError());
 		rte_errno = EINVAL;
-		return -1;
+		ret = -1;
+		goto exit;
 	}
 
 	info = infos;
 	while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-		unsigned int node_id = info->NumaNode.NodeNumber;
-		GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
-		struct lcore_map *lcore;
-		unsigned int i, socket_id;
-
-		/* NUMA node may be reported multiple times if it includes
-		 * cores from different processor groups, e. g. 80 cores
-		 * of a physical processor comprise one NUMA node, but two
-		 * processor groups, because group size is limited by 32/64.
-		 */
-		for (socket_id = 0; socket_id < cpu_map.socket_count;
-		    socket_id++) {
-			if (cpu_map.sockets[socket_id].node_id == node_id)
-				break;
-		}
-
-		if (socket_id == cpu_map.socket_count) {
-			if (socket_id == RTE_DIM(cpu_map.sockets)) {
-				full = true;
-				goto exit;
-			}
-
-			cpu_map.sockets[socket_id].node_id = node_id;
-			cpu_map.socket_count++;
-		}
-
-		for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-			if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-				continue;
-
-			if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
-				full = true;
-				goto exit;
-			}
-
-			lcore = &cpu_map.lcores[cpu_map.lcore_count];
-			lcore->socket_id = socket_id;
-			lcore->core_id =
-				cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-			cpu_map.lcore_count++;
+		if (eal_create_lcore_map(info)) {
+			full = true;
+			break;
 		}
 
 		info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
 			(uint8_t *)info + info->Size);
 	}
 
+	if (eal_query_group_affinity()) {
+		/*
+		 * No need to set rte_errno here.
+		 * It is set by eal_query_group_affinity().
+		 */
+		ret = -1;
+		goto exit;
+	}
 exit:
 	if (full) {
 		/* Not a fatal error, but important for troubleshooting. */
@@ -138,7 +216,7 @@ eal_create_cpu_map(void)
 
 	free(infos);
 
-	return 0;
+	return ret;
 }
 
 int
@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)
 {
 	return cpu_map.sockets[socket_id].node_id;
 }
+
+PGROUP_AFFINITY
+eal_get_cpu_affinity(size_t cpu_index)
+{
+	RTE_VERIFY(cpu_index < CPU_SETSIZE);
+
+	return &cpu_map.cpus[cpu_index];
+}
diff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h
index 23ead6d30c..355ef181a5 100644
--- a/lib/eal/windows/eal_windows.h
+++ b/lib/eal/windows/eal_windows.h
@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Get pointer to the group affinity for the cpu.
+ *
+ * @param cpu_index
+ *  Index of the cpu, as it comes from rte_cpuset_t.
+ * @return
+ *  Pointer to the group affinity for the cpu.
+ */
+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);
+
 /**
  * Schedule code for execution in the interrupt thread.
  *
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index c1ecfbd6ae..0127119f49 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -7,7 +7,8 @@
 #include <rte_debug.h>
 #include <rte_errno.h>
 #include <rte_thread.h>
-#include <rte_windows.h>
+
+#include "eal_windows.h"
 
 struct eal_tls_key {
 	DWORD thread_index;
@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
 	return t1.opaque_id == t2.opaque_id;
 }
 
+static int
+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
+		PGROUP_AFFINITY affinity)
+{
+	int ret = 0;
+	PGROUP_AFFINITY cpu_affinity = NULL;
+	unsigned int cpu_idx;
+
+	memset(affinity, 0, sizeof(GROUP_AFFINITY));
+	affinity->Group = (USHORT)-1;
+
+	/* Check that all cpus of the set belong to the same processor group and
+	 * accumulate thread affinity to be applied.
+	 */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+		if (!CPU_ISSET(cpu_idx, cpuset))
+			continue;
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if (affinity->Group == (USHORT)-1) {
+			affinity->Group = cpu_affinity->Group;
+		} else if (affinity->Group != cpu_affinity->Group) {
+			ret = EINVAL;
+			goto cleanup;
+		}
+
+		affinity->Mask |= cpu_affinity->Mask;
+	}
+
+	if (affinity->Mask == 0) {
+		ret = EINVAL;
+		goto cleanup;
+	}
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_affinity_by_id(rte_thread_t thread_id,
+		const rte_cpuset_t *cpuset)
+{
+	int ret = 0;
+	GROUP_AFFINITY thread_affinity;
+	HANDLE thread_handle = NULL;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	ret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
+		ret = thread_log_last_error("SetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_get_affinity_by_id(rte_thread_t thread_id,
+		rte_cpuset_t *cpuset)
+{
+	HANDLE thread_handle = NULL;
+	PGROUP_AFFINITY cpu_affinity;
+	GROUP_AFFINITY thread_affinity;
+	unsigned int cpu_idx;
+	int ret = 0;
+
+	RTE_VERIFY(cpuset != NULL);
+
+	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	/* obtain previous thread affinity */
+	if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
+		ret = thread_log_last_error("GetThreadGroupAffinity()");
+		goto cleanup;
+	}
+
+	CPU_ZERO(cpuset);
+
+	/* Convert affinity to DPDK cpu set */
+	for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
+
+		cpu_affinity = eal_get_cpu_affinity(cpu_idx);
+
+		if ((cpu_affinity->Group == thread_affinity.Group) &&
+		   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
+			CPU_SET(cpu_idx, cpuset);
+		}
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 5/8] eal: implement thread priority management functions
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
                                                             ` (3 preceding siblings ...)
  2021-11-11  1:33                                           ` [PATCH v18 4/8] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 6/8] eal: add thread lifetime management Narcisa Ana Maria Vasile
                                                             ` (2 subsequent siblings)
  7 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for setting and getting the priority of a thread.
Priorities on multiple platforms are similarly determined by
a priority value and a priority class/policy.

Currently in DPDK most threads operate at the OS-default
priority level but there are cases when increasing the
priority is useful. For example, high performance applications
may require elevated priority levels.

For these reasons, EAL will expose two priority levels which
are named suggestively "normal" and "realtime_critical"
and are computed as follows:

On Linux, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* policy SCHED_OTHER
* priority value:   (sched_get_priority_min(SCHED_OTHER) +
                     sched_get_priority_max(SCHED_OTHER))/2;
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* policy SCHED_RR
* priority value: sched_get_priority_max(SCHED_RR);

On Windows, the following mapping is created:
RTE_THREAD_PRIORITY_NORMAL corresponds to
* class NORMAL_PRIORITY_CLASS
* priority THREAD_PRIORITY_NORMAL
RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to
* class REALTIME_PRIORITY_CLASS
* priority THREAD_PRIORITY_TIME_CRITICAL

Note that on Linux the resulting priority value will be 0,
in accordance to the docs that mention the value
should be 0 for SCHED_OTHER policy.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 lib/eal/common/rte_thread.c  | 103 ++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  34 ++++++++++
 lib/eal/version.map          |   2 +
 lib/eal/windows/rte_thread.c | 127 +++++++++++++++++++++++++++++++++++
 4 files changed, 266 insertions(+)

diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 73b7b3141c..fc5d7c5b1a 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -50,6 +50,109 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 		sizeof(*cpuset), cpuset);
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pol)
+{
+	/* Clear the output parameters */
+	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
+	*pol = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pol = SCHED_OTHER;
+
+		/*
+		 * Choose the middle of the range to represent
+		 * the priority 'normal'.
+		 * On Linux, this should be 0, since both
+		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
+		 */
+		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
+			sched_get_priority_max(SCHED_OTHER))/2;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pol = SCHED_RR;
+		*os_pri = sched_get_priority_max(SCHED_RR);
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_priority(int policy, int os_pri,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (policy) {
+	case SCHED_OTHER:
+		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
+				sched_get_priority_max(SCHED_OTHER))/2) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case SCHED_RR:
+		if (os_pri == sched_get_priority_max(SCHED_RR)) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+	ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
+			&param);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
+		goto cleanup;
+	}
+
+	return thread_map_os_priority_to_eal_priority(policy,
+			param.sched_priority, priority);
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority)
+{
+	int ret;
+	int policy;
+	struct sched_param param;
+
+/* Realtime priority can cause crashes on non-Windows platforms. */
+#ifndef RTE_EXEC_ENV_WINDOWS
+	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL)
+		return ENOTSUP;
+#endif
+
+	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
+		&policy);
+	if (ret != 0)
+		return ret;
+
+	return pthread_setschedparam((pthread_t)thread_id.opaque_id,
+		policy, &param);
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 5b100cafda..7077c9ce46 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -213,6 +213,40 @@ void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Get the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to get priority.
+ *
+ * @param priority
+ *   Location to store the retrieved priority.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority);
+
+/**
+ * Set the priority of a thread.
+ *
+ * @param thread_id
+ *    Id of the thread for which to set priority.
+ *
+ * @param priority
+ *   Priority value to be set.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_set_priority(rte_thread_t thread_id,
+		enum rte_thread_priority priority);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 193a79a4d2..5bc5a6cf76 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -429,6 +429,8 @@ EXPERIMENTAL {
 	rte_thread_attr_set_priority;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
+	rte_thread_get_priority;
+	rte_thread_set_priority;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 0127119f49..5c02a6eaff 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -200,6 +200,133 @@ rte_thread_get_affinity_by_id(rte_thread_t thread_id,
 	return ret;
 }
 
+static int
+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,
+		int *os_pri, int *pri_class)
+{
+	/* Clear the output parameters */
+	*os_pri = -1;
+	*pri_class = -1;
+
+	switch (eal_pri) {
+	case RTE_THREAD_PRIORITY_NORMAL:
+		*pri_class = NORMAL_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_NORMAL;
+		break;
+	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
+		*pri_class = REALTIME_PRIORITY_CLASS;
+		*os_pri = THREAD_PRIORITY_TIME_CRITICAL;
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+thread_map_os_priority_to_eal_value(int os_pri, int pri_class,
+		enum rte_thread_priority *eal_pri)
+{
+	switch (pri_class) {
+	case NORMAL_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_NORMAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
+			return 0;
+		}
+		break;
+	case REALTIME_PRIORITY_CLASS:
+		if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {
+			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
+			return 0;
+		}
+		break;
+	default:
+		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
+		return EINVAL;
+	}
+	return 0;
+}
+
+int
+rte_thread_get_priority(rte_thread_t thread_id,
+		enum rte_thread_priority *priority)
+{
+	HANDLE thread_handle = NULL;
+	DWORD pri_class;
+	int os_pri;
+	int ret;
+
+	pri_class = GetPriorityClass(GetCurrentProcess());
+	if (pri_class == 0) {
+		ret = thread_log_last_error("GetPriorityClass()");
+		goto cleanup;
+	}
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+			THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	os_pri = GetThreadPriority(thread_handle);
+	if (os_pri == THREAD_PRIORITY_ERROR_RETURN) {
+		ret = thread_log_last_error("GetThreadPriority()");
+		goto cleanup;
+	}
+
+	ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);
+	if (ret != 0)
+		goto cleanup;
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
+int
+rte_thread_set_priority(rte_thread_t thread_id,
+			enum rte_thread_priority priority)
+{
+	HANDLE thread_handle;
+	int priority_class;
+	int os_priority;
+	int ret = 0;
+
+	thread_handle = OpenThread(THREAD_SET_INFORMATION |
+		THREAD_QUERY_INFORMATION, FALSE,
+		thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	ret = thread_map_priority_to_os_value(priority, &os_priority,
+		&priority_class);
+	if (ret != 0)
+		goto cleanup;
+
+	if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
+		ret = thread_log_last_error("SetPriorityClass()");
+		goto cleanup;
+	}
+
+	if (!SetThreadPriority(thread_handle, os_priority)) {
+		ret = thread_log_last_error("SetThreadPriority()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL)
+		CloseHandle(thread_handle);
+
+	return ret;
+}
+
 int
 rte_thread_attr_init(rte_thread_attr_t *attr)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 6/8] eal: add thread lifetime management
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
                                                             ` (4 preceding siblings ...)
  2021-11-11  1:33                                           ` [PATCH v18 5/8] eal: implement thread priority management functions Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 7/8] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 8/8] eal: implement functions for mutex management Narcisa Ana Maria Vasile
  7 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for thread creation, joining, detaching.

The *rte_thread_create()* function can optionally receive
an rte_thread_attr_t object that will cause the thread to be
created with the affinity and priority described by the
attributes object. If no rte_thread_attr_t is passed (parameter is NULL),
the default affinity and priority are used.

On Windows, the function executed by a thread when the thread starts is
represeneted by a function pointer of type DWORD (*func) (void*).
On other platforms, the function pointer is a void* (*func) (void*).

Performing a cast between these two types of function pointers to
uniformize the API on all platforms may result in undefined behavior.
TO fix this issue, a wrapper that respects the signature required by
CreateThread() has been created on Windows.

Add unit tests:
 - verify rte_thread_self() correctly retrieves the thread id.
 - verify that affinity and priority can be set successfully.
 - verify that threads are created and cleaned up correctly.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/meson.build            |   2 +
 app/test/test_threads.c         | 217 ++++++++++++++++++++++++++++++++
 lib/eal/common/rte_thread.c     | 111 ++++++++++++++++
 lib/eal/include/rte_thread.h    |  55 ++++++++
 lib/eal/version.map             |   3 +
 lib/eal/windows/include/sched.h |   2 +-
 lib/eal/windows/rte_thread.c    | 134 ++++++++++++++++++++
 7 files changed, 523 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_threads.c

diff --git a/app/test/meson.build b/app/test/meson.build
index 96670c3504..9fd34459e9 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -146,6 +146,7 @@ test_sources = files(
         'test_tailq.c',
         'test_thash.c',
         'test_thash_perf.c',
+        'test_threads.c',
         'test_timer.c',
         'test_timer_perf.c',
         'test_timer_racecond.c',
@@ -287,6 +288,7 @@ fast_tests = [
         ['reorder_autotest', true],
         ['service_autotest', true],
         ['thash_autotest', true],
+        ['threads_autotest', true],
         ['trace_autotest', true],
 ]
 
diff --git a/app/test/test_threads.c b/app/test/test_threads.c
new file mode 100644
index 0000000000..9fcae34179
--- /dev/null
+++ b/app/test/test_threads.c
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Microsoft.
+ */
+
+#include <rte_thread.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+#define THREADS_COUNT 20
+
+RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO);
+
+static void *
+thread_loop_self(void *arg)
+{
+	rte_thread_t *id = arg;
+
+	*id = rte_thread_self();
+
+	return NULL;
+}
+
+static int
+test_thread_self(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_t self_ids[THREADS_COUNT] = {};
+	int ret;
+	int i;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL, thread_loop_self,
+				&self_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		RTE_TEST_ASSERT(rte_thread_join(threads_ids[i], NULL) == 0, "Failed to join thread!");
+		RTE_TEST_ASSERT_EQUAL(threads_ids[i].opaque_id,
+				self_ids[i].opaque_id, "Unexpected thread id!");
+	}
+
+	return 0;
+}
+
+struct thread_affinity_ctx {
+	rte_cpuset_t *cpuset;
+	unsigned int result;
+};
+
+static void *
+thread_loop_attributes_affinity(void *arg)
+{
+	struct thread_affinity_ctx *ctx = arg;
+	rte_cpuset_t cpuset;
+	size_t i;
+
+	ctx->result = 0;
+
+	CPU_ZERO(&cpuset);
+	if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0) {
+		ctx->result = 1;
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to get thread affinity!");
+		return NULL;
+	}
+
+	/*
+	 * Check that the thread is not running on CPUs which were not
+	 * specified in the affinity mask. Note that the CPU mask
+	 * retrieved above can be different than the original mask specified
+	 * with rte_thread_attr_set_affinity(), since some CPUs may not be
+	 * available on the system.
+	 */
+	for (i = 0; i < CPU_SETSIZE; ++i) {
+		if (!CPU_ISSET(i, ctx->cpuset) && CPU_ISSET(i, &cpuset)) {
+			ctx->result = 1;
+			rte_log(RTE_LOG_DEBUG, threads_logtype_test, "CPU %zu should not be set for this thread!\n",
+					i);
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_affinity(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	struct thread_affinity_ctx ctx[THREADS_COUNT] = {};
+	rte_thread_attr_t attr;
+	rte_cpuset_t cpuset;
+	size_t i;
+	int ret = 0;
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize thread attributes!");
+
+	CPU_ZERO(&cpuset);
+	ret = rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset);
+	RTE_TEST_ASSERT(ret == 0, "Failed to get main thread affinity!");
+
+	ret = rte_thread_attr_set_affinity(&attr, &cpuset);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread attributes!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ctx[i].cpuset = &cpuset;
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_attributes_affinity, &ctx[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(ctx[i].result, 0, "Unexpected thread affinity!");
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_priority(void *arg)
+{
+	int ret;
+	enum rte_thread_priority priority;
+	int *result = arg;
+
+	*result = 1;
+	ret = rte_thread_get_priority(rte_thread_self(), &priority);
+	if (ret != 0 || priority != RTE_THREAD_PRIORITY_NORMAL)
+		*result = 2;
+
+	return NULL;
+}
+
+static int
+test_thread_attributes_priority(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	rte_thread_attr_t attr;
+	size_t i;
+	int ret = 0;
+	int results[THREADS_COUNT] = {};
+
+	ret = rte_thread_attr_init(&attr);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize  thread attributes!");
+
+	ret = rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to set thread priority!");
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], &attr,
+				thread_loop_priority, &results[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_join(threads_ids[i], NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+		RTE_TEST_ASSERT_EQUAL(results[i], 1, "Unexpected priority value!");
+	}
+
+	return ret;
+}
+
+static void *
+thread_loop_return(void *arg)
+{
+	RTE_SET_USED(arg);
+	return NULL;
+}
+
+static int
+test_thread_detach(void)
+{
+	rte_thread_t threads_ids[THREADS_COUNT];
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_create(&threads_ids[i], NULL,
+				thread_loop_return, NULL);
+		RTE_TEST_ASSERT(ret == 0, "Failed to create threads!");
+	}
+
+	for (i = 0; i < THREADS_COUNT; ++i) {
+		ret = rte_thread_detach(threads_ids[i]);
+		RTE_TEST_ASSERT(ret == 0, "Failed to detach thread!");
+	}
+
+	return ret;
+}
+
+static struct unit_test_suite threads_test_suite = {
+	.suite_name = "threads autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+			TEST_CASE(test_thread_self),
+			TEST_CASE(test_thread_attributes_affinity),
+			TEST_CASE(test_thread_attributes_priority),
+			TEST_CASE(test_thread_detach),
+			TEST_CASES_END()
+	}
+};
+
+static int
+test_threads(void)
+{
+	return unit_test_suite_runner(&threads_test_suite);
+}
+
+REGISTER_TEST_COMMAND(threads_autotest, test_threads);
diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index fc5d7c5b1a..910c39eb88 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -198,6 +198,117 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+int
+rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	pthread_attr_t attr;
+	pthread_attr_t *attrp = NULL;
+	struct sched_param param = {
+		.sched_priority = 0,
+	};
+	int policy = SCHED_OTHER;
+
+	if (thread_attr != NULL) {
+		ret = pthread_attr_init(&attr);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
+			goto cleanup;
+		}
+
+		attrp = &attr;
+
+		/*
+		 * Set the inherit scheduler parameter to explicit,
+		 * otherwise the priority attribute is ignored.
+		 */
+		ret = pthread_attr_setinheritsched(attrp,
+				PTHREAD_EXPLICIT_SCHED);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
+			goto cleanup;
+		}
+
+
+/* Realtime priority can cause crashes on non-Windows platforms. */
+#ifndef RTE_EXEC_ENV_WINDOWS
+		if (thread_attr->priority ==
+				RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
+			ret = ENOTSUP;
+			goto cleanup;
+		}
+#endif
+		ret = thread_map_priority_to_os_value(thread_attr->priority,
+				&param.sched_priority, &policy);
+		if (ret != 0)
+			goto cleanup;
+
+		ret = pthread_attr_setschedpolicy(attrp, policy);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
+			goto cleanup;
+		}
+
+		ret = pthread_attr_setschedparam(attrp, &param);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
+			goto cleanup;
+		}
+	}
+
+	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
+		thread_func, args);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
+		goto cleanup;
+	}
+
+	if (thread_attr != NULL && CPU_COUNT(&thread_attr->cpuset) > 0) {
+		ret = rte_thread_set_affinity_by_id(*thread_id,
+			&thread_attr->cpuset);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "rte_thread_set_affinity_by_id failed\n");
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	if (attrp != NULL)
+		pthread_attr_destroy(&attr);
+
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	int ret = 0;
+	void *res = NULL;
+	void **pres = NULL;
+
+	if (value_ptr != NULL)
+		pres = &res;
+
+	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
+		return ret;
+	}
+
+	if (value_ptr != NULL && *pres != NULL)
+		*value_ptr = *(unsigned long *)(*pres);
+
+	return 0;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	return pthread_detach((pthread_t)thread_id.opaque_id);
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7077c9ce46..e841321819 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -31,6 +31,7 @@ typedef struct rte_thread_tag {
 	uintptr_t opaque_id; /**< thread identifier */
 } rte_thread_t;
 
+typedef void* (*rte_thread_func) (void *);
 /**
  * Thread priority values.
  */
@@ -211,6 +212,60 @@ int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
  */
 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
 
+/**
+ * Create a new thread that will invoke the 'thread_func' routine.
+ *
+ * @param thread_id
+ *    A pointer that will store the id of the newly created thread.
+ *
+ * @param thread_attr
+ *    Attributes that are used at the creation of the new thread.
+ *
+ * @param thread_func
+ *    The routine that the new thread will invoke when starting execution.
+ *
+ * @param args
+ *    Arguments to be passed to the 'thread_func' routine.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_create(rte_thread_t *thread_id,
+		const rte_thread_attr_t *thread_attr,
+		rte_thread_func thread_func, void *args);
+
+/**
+ * Waits for the thread identified by 'thread_id' to terminate
+ *
+ * @param thread_id
+ *    The identifier of the thread.
+ *
+ * @param value_ptr
+ *    Stores the exit status of the thread.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr);
+
+/**
+ * Indicate that the return value of the thread is not needed and
+ * all thread resources should be release when the thread terminates.
+ *
+ * @param thread_id
+ *    The id of the thread to be detached.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_detach(rte_thread_t thread_id);
+
 #endif /* RTE_HAS_CPUSET */
 
 /**
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 5bc5a6cf76..0384a09fa2 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -431,6 +431,9 @@ EXPERIMENTAL {
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
 	rte_thread_set_priority;
+	rte_thread_create;
+	rte_thread_join;
+	rte_thread_detach;
 };
 
 INTERNAL {
diff --git a/lib/eal/windows/include/sched.h b/lib/eal/windows/include/sched.h
index bc31cc8465..912fed12c2 100644
--- a/lib/eal/windows/include/sched.h
+++ b/lib/eal/windows/include/sched.h
@@ -44,7 +44,7 @@ typedef struct _rte_cpuset_s {
 	(1LL << _WHICH_BIT(b))) != 0LL)
 
 static inline int
-count_cpu(rte_cpuset_t *s)
+count_cpu(const rte_cpuset_t *s)
 {
 	unsigned int _i;
 	int count = 0;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 5c02a6eaff..669a68d6a8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -14,6 +14,11 @@ struct eal_tls_key {
 	DWORD thread_index;
 };
 
+struct thread_routine_ctx {
+	rte_thread_func thread_func;
+	void *routine_args;
+};
+
 /* Translates the most common error codes related to threads */
 static int
 thread_translate_win32_error(DWORD error)
@@ -370,6 +375,135 @@ rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
 	return 0;
 }
 
+static DWORD
+thread_func_wrapper(void *args)
+{
+	struct thread_routine_ctx *pctx = args;
+	struct thread_routine_ctx ctx;
+
+	ctx.thread_func = pctx->thread_func;
+	ctx.routine_args = pctx->routine_args;
+
+	free(pctx);
+
+	return (DWORD)(uintptr_t)ctx.thread_func(ctx.routine_args);
+}
+
+int
+rte_thread_create(rte_thread_t *thread_id,
+		  const rte_thread_attr_t *thread_attr,
+		  rte_thread_func thread_func, void *args)
+{
+	int ret = 0;
+	DWORD tid;
+	HANDLE thread_handle = NULL;
+	GROUP_AFFINITY thread_affinity;
+	struct thread_routine_ctx *ctx = NULL;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (ctx == NULL) {
+		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ctx->routine_args = args;
+	ctx->thread_func = thread_func;
+
+	thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx,
+		CREATE_SUSPENDED, &tid);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("CreateThread()");
+		free(ctx);
+		goto cleanup;
+	}
+	thread_id->opaque_id = tid;
+
+	if (thread_attr != NULL) {
+		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
+			ret = rte_convert_cpuset_to_affinity(
+							&thread_attr->cpuset,
+							&thread_affinity
+							);
+			if (ret != 0) {
+				RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
+				goto cleanup;
+			}
+
+			if (!SetThreadGroupAffinity(thread_handle,
+						    &thread_affinity, NULL)) {
+				ret = thread_log_last_error("SetThreadGroupAffinity()");
+				goto cleanup;
+			}
+		}
+		ret = rte_thread_set_priority(*thread_id,
+				thread_attr->priority);
+		if (ret != 0) {
+			RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n");
+			goto cleanup;
+		}
+	}
+
+	if (ResumeThread(thread_handle) == (DWORD)-1) {
+		ret = thread_log_last_error("ResumeThread()");
+		goto cleanup;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+	return ret;
+}
+
+int
+rte_thread_join(rte_thread_t thread_id, unsigned long *value_ptr)
+{
+	HANDLE thread_handle;
+	DWORD result;
+	DWORD exit_code = 0;
+	BOOL err;
+	int ret = 0;
+
+	thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+				   FALSE, thread_id.opaque_id);
+	if (thread_handle == NULL) {
+		ret = thread_log_last_error("OpenThread()");
+		goto cleanup;
+	}
+
+	result = WaitForSingleObject(thread_handle, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		ret = thread_log_last_error("WaitForSingleObject()");
+		goto cleanup;
+	}
+
+	if (value_ptr != NULL) {
+		err = GetExitCodeThread(thread_handle, &exit_code);
+		if (err == 0) {
+			ret = thread_log_last_error("GetExitCodeThread()");
+			goto cleanup;
+		}
+		*value_ptr = exit_code;
+	}
+
+cleanup:
+	if (thread_handle != NULL) {
+		CloseHandle(thread_handle);
+		thread_handle = NULL;
+	}
+
+	return ret;
+}
+
+int
+rte_thread_detach(rte_thread_t thread_id)
+{
+	/* No resources that need to be released. */
+	RTE_SET_USED(thread_id);
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 7/8] eal: implement functions for thread barrier management
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
                                                             ` (5 preceding siblings ...)
  2021-11-11  1:33                                           ` [PATCH v18 6/8] eal: add thread lifetime management Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-11-11  1:33                                           ` [PATCH v18 8/8] eal: implement functions for mutex management Narcisa Ana Maria Vasile
  7 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for barrier init, destroy, wait.

A portable type is used to represent a barrier identifier.
The rte_thread_barrier_wait() function returns the same value
on all platforms.

Add unit tests to verify that the barrier correctly
synchronizes all threads. Verify that the threads are unblocked
after the required number of threads have called barrier_wait().

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/test_threads.c      | 49 +++++++++++++++++++++++++++++
 lib/eal/common/rte_thread.c  | 61 ++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_thread.h | 58 ++++++++++++++++++++++++++++++++++
 lib/eal/version.map          |  3 ++
 lib/eal/windows/rte_thread.c | 56 +++++++++++++++++++++++++++++++++
 5 files changed, 227 insertions(+)

diff --git a/app/test/test_threads.c b/app/test/test_threads.c
index 9fcae34179..00f604ab7e 100644
--- a/app/test/test_threads.c
+++ b/app/test/test_threads.c
@@ -195,6 +195,54 @@ test_thread_detach(void)
 	return ret;
 }
 
+struct thread_context {
+	rte_thread_barrier *barrier;
+	int barrier_result;
+};
+
+static void *
+thread_loop_barrier(void *arg)
+{
+	struct thread_context *ctx = arg;
+
+	ctx->barrier_result = rte_thread_barrier_wait(ctx->barrier);
+	if (ctx->barrier_result > 0)
+		rte_log(RTE_LOG_DEBUG, threads_logtype_test, "Failed to wait at barrier!");
+
+	return NULL;
+}
+
+static int
+test_thread_barrier(void)
+{
+	rte_thread_t thread_id;
+	struct thread_context ctx;
+	rte_thread_barrier barrier;
+	int ret = 0;
+	int result = 0;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	ctx.barrier = &barrier;
+	ret = rte_thread_create(&thread_id, NULL, thread_loop_barrier, &ctx);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	result = rte_thread_barrier_wait(&barrier);
+	RTE_TEST_ASSERT(result <= 0, "Failed to wait at the barrier!");
+
+	ret = rte_thread_join(thread_id, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join threads!");
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	RTE_TEST_ASSERT(ctx.barrier_result <= 0, "Child thread failed to wait at the barrier!");
+	RTE_TEST_ASSERT_NOT_EQUAL(ctx.barrier_result, result, "Threads were not blocked at the barrier!");
+
+	return 0;
+}
+
 static struct unit_test_suite threads_test_suite = {
 	.suite_name = "threads autotest",
 	.setup = NULL,
@@ -204,6 +252,7 @@ static struct unit_test_suite threads_test_suite = {
 			TEST_CASE(test_thread_attributes_affinity),
 			TEST_CASE(test_thread_attributes_priority),
 			TEST_CASE(test_thread_detach),
+			TEST_CASE(test_thread_barrier),
 			TEST_CASES_END()
 	}
 };
diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index 910c39eb88..d30a8a7ca3 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -309,6 +309,67 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	pthread_barrier_t *pthread_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	pthread_barrier = calloc(1, sizeof(*pthread_barrier));
+	if (pthread_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	ret = pthread_barrier_init(pthread_barrier, NULL, count);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init barrier, ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	barrier->barrier_id = pthread_barrier;
+	pthread_barrier = NULL;
+
+cleanup:
+	free(pthread_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	ret = pthread_barrier_wait(barrier->barrier_id);
+	if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
+		ret = RTE_THREAD_BARRIER_SERIAL_THREAD;
+
+	return ret;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	int ret = 0;
+
+	RTE_VERIFY(barrier != NULL);
+
+	ret = pthread_barrier_destroy(barrier->barrier_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Failed to destroy barrier: %d\n", ret);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index e841321819..7c84e32988 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,18 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+/**
+ * Returned by rte_thread_barrier_wait() when call is successful.
+ */
+#define RTE_THREAD_BARRIER_SERIAL_THREAD -1
+
+/**
+ * Thread barrier representation.
+ */
+typedef struct rte_thread_barrier_tag {
+	void *barrier_id;  /**< barrrier identifier */
+} rte_thread_barrier;
+
 /**
  * TLS key type, an opaque pointer.
  */
@@ -302,6 +314,52 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a synchronization barrier.
+ *
+ * @param barrier
+ *    A pointer that references the newly created 'barrier' object.
+ *
+ * @param count
+ *    The number of threads that must enter the barrier before
+ *    the threads can continue execution.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_init(rte_thread_barrier *barrier, int count);
+
+/**
+ * Causes the calling thread to wait at the synchronization barrier 'barrier'.
+ *
+ * @param barrier
+ *    The barrier used for synchronizing the threads.
+ *
+ * @return
+ *   Return RTE_THREAD_BARRIER_SERIAL_THREAD for the thread synchronized
+ *      at the barrier.
+ *   Return 0 for all other threads.
+ *   Return a positive errno-style error number, in case of failure.
+ */
+__rte_experimental
+int rte_thread_barrier_wait(rte_thread_barrier *barrier);
+
+/**
+ * Releases all resources used by a synchronization barrier
+ * and uninitializes it.
+ *
+ * @param barrier
+ *    The barrier to be destroyed.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_barrier_destroy(rte_thread_barrier *barrier);
+
 /**
  * Create a TLS data key visible to all threads in the process.
  * the created key is later used to get/set a value.
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 0384a09fa2..06e5f82da2 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -427,6 +427,9 @@ EXPERIMENTAL {
 	rte_thread_attr_get_affinity;
 	rte_thread_attr_set_affinity;
 	rte_thread_attr_set_priority;
+	rte_thread_barrier_init;
+	rte_thread_barrier_wait;
+	rte_thread_barrier_destroy;
 	rte_thread_get_affinity_by_id;
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 669a68d6a8..3f72bbf716 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -504,6 +504,62 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
+{
+	int ret = 0;
+	SYNCHRONIZATION_BARRIER *sync_barrier = NULL;
+
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(count > 0);
+
+	sync_barrier = calloc(1, sizeof(*sync_barrier));
+	if (sync_barrier == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize barrier. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+	if (!InitializeSynchronizationBarrier(sync_barrier, count, -1)) {
+		ret = thread_log_last_error("InitializeSynchronizationBarrier()");
+		goto cleanup;
+	}
+
+	barrier->barrier_id = sync_barrier;
+	sync_barrier = NULL;
+
+cleanup:
+	free(sync_barrier);
+	return ret;
+}
+
+int
+rte_thread_barrier_wait(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+	RTE_VERIFY(barrier->barrier_id != NULL);
+
+	if (EnterSynchronizationBarrier(barrier->barrier_id,
+				SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)) {
+
+		return RTE_THREAD_BARRIER_SERIAL_THREAD;
+	}
+
+	return 0;
+}
+
+int
+rte_thread_barrier_destroy(rte_thread_barrier *barrier)
+{
+	RTE_VERIFY(barrier != NULL);
+
+	DeleteSynchronizationBarrier(barrier->barrier_id);
+
+	free(barrier->barrier_id);
+	barrier->barrier_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_key_create(rte_thread_key *key,
 		__rte_unused void (*destructor)(void *))
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* [PATCH v18 8/8] eal: implement functions for mutex management
  2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
                                                             ` (6 preceding siblings ...)
  2021-11-11  1:33                                           ` [PATCH v18 7/8] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
@ 2021-11-11  1:33                                           ` Narcisa Ana Maria Vasile
  2021-12-13 20:27                                             ` Narcisa Ana Maria Vasile
  7 siblings, 1 reply; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-11-11  1:33 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

From: Narcisa Vasile <navasile@microsoft.com>

Add functions for mutex init, destroy, lock, unlock, trylock.

Windows does not have a static initializer. Initialization
is only done through InitializeCriticalSection(). To overcome this,
RTE_INIT_MUTEX macro is added to replace static initialization
of mutexes. The macro calls rte_thread_mutex_init().

Add unit tests to verify that the mutex correctly locks/unlocks
and protects the data. Check both static and dynamic mutexes.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
---
 app/test/test_threads.c      | 106 +++++++++++++++++++++++++++++++++++
 lib/eal/common/rte_thread.c  |  69 +++++++++++++++++++++++
 lib/eal/include/rte_thread.h |  85 ++++++++++++++++++++++++++++
 lib/eal/version.map          |   5 ++
 lib/eal/windows/rte_thread.c |  64 +++++++++++++++++++++
 5 files changed, 329 insertions(+)

diff --git a/app/test/test_threads.c b/app/test/test_threads.c
index 00f604ab7e..91155a04e3 100644
--- a/app/test/test_threads.c
+++ b/app/test/test_threads.c
@@ -243,6 +243,110 @@ test_thread_barrier(void)
 	return 0;
 }
 
+RTE_INIT_MUTEX(static_mutex);
+
+struct mutex_loop_args {
+	rte_thread_barrier *barrier;
+	rte_thread_mutex *mutex;
+	unsigned long result_A;
+	unsigned long result_B;
+};
+
+static void *
+thread_loop_mutex_B(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) == 0) {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_B = 1;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_B = 2;
+	}
+
+	return NULL;
+}
+
+static void *
+thread_loop_mutex_A(void *arg)
+{
+	struct mutex_loop_args *args = arg;
+
+	if (rte_thread_mutex_try_lock(args->mutex) != 0) {
+		rte_thread_barrier_wait(args->barrier);
+		args->result_A = 2;
+	} else {
+		rte_thread_barrier_wait(args->barrier);
+		rte_thread_mutex_unlock(args->mutex);
+		args->result_A = 1;
+	}
+
+	return NULL;
+}
+
+static int
+test_thread_mutex(rte_thread_mutex *pmutex)
+{
+	rte_thread_t thread_A;
+	rte_thread_t thread_B;
+	rte_thread_mutex mutex;
+	rte_thread_barrier barrier;
+	struct mutex_loop_args args;
+	int ret = 0;
+
+	/* If mutex is not statically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_init(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to initialize mutex!");
+	} else
+		mutex = *pmutex;
+
+	ret = rte_thread_barrier_init(&barrier, 2);
+	RTE_TEST_ASSERT(ret == 0, "Failed to initialize barrier!");
+
+	args.mutex = &mutex;
+	args.barrier = &barrier;
+
+	ret = rte_thread_create(&thread_A, NULL, thread_loop_mutex_A, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_create(&thread_B, NULL, thread_loop_mutex_B, &args);
+	RTE_TEST_ASSERT(ret == 0, "Failed to create thread!");
+
+	ret = rte_thread_join(thread_A, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	ret = rte_thread_join(thread_B, NULL);
+	RTE_TEST_ASSERT(ret == 0, "Failed to join thread!");
+
+	RTE_TEST_ASSERT(args.result_A != args.result_B, "Mutex failed to be acquired or was acquired by both threads!");
+
+	/* Destroy if dynamically initialized */
+	if (pmutex == NULL) {
+		ret = rte_thread_mutex_destroy(&mutex);
+		RTE_TEST_ASSERT(ret == 0, "Failed to destroy mutex!");
+	}
+
+	ret = rte_thread_barrier_destroy(&barrier);
+	RTE_TEST_ASSERT(ret == 0, "Failed to destroy barrier!");
+
+	return ret;
+}
+
+static int
+test_thread_mutex_static(void)
+{
+	return test_thread_mutex(&static_mutex);
+}
+
+static int
+test_thread_mutex_dynamic(void)
+{
+	return test_thread_mutex(NULL);
+}
+
 static struct unit_test_suite threads_test_suite = {
 	.suite_name = "threads autotest",
 	.setup = NULL,
@@ -253,6 +357,8 @@ static struct unit_test_suite threads_test_suite = {
 			TEST_CASE(test_thread_attributes_priority),
 			TEST_CASE(test_thread_detach),
 			TEST_CASE(test_thread_barrier),
+			TEST_CASE(test_thread_mutex_static),
+			TEST_CASE(test_thread_mutex_dynamic),
 			TEST_CASES_END()
 	}
 };
diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c
index d30a8a7ca3..4a9a1b6e07 100644
--- a/lib/eal/common/rte_thread.c
+++ b/lib/eal/common/rte_thread.c
@@ -309,6 +309,75 @@ rte_thread_detach(rte_thread_t thread_id)
 	return pthread_detach((pthread_t)thread_id.opaque_id);
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	pthread_mutex_t *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	ret = pthread_mutex_init(m, NULL);
+	if (ret != 0) {
+		RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret);
+		goto cleanup;
+	}
+
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	free(m);
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	return pthread_mutex_trylock((pthread_mutex_t *)mutex->mutex_id);
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	RTE_VERIFY(mutex != NULL);
+
+	ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id);
+	if (ret != 0)
+		RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret);
+
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return ret;
+}
+
 int
 rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
 {
diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h
index 7c84e32988..09a5fd8add 100644
--- a/lib/eal/include/rte_thread.h
+++ b/lib/eal/include/rte_thread.h
@@ -54,6 +54,25 @@ typedef struct {
 
 #endif /* RTE_HAS_CPUSET */
 
+#define RTE_DECLARE_MUTEX(private_lock)          rte_thread_mutex private_lock
+
+#define RTE_DEFINE_MUTEX(private_lock)\
+RTE_INIT(__rte_ ## private_lock ## _init)\
+{\
+	RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\
+}
+
+#define RTE_INIT_MUTEX(private_lock)\
+static RTE_DECLARE_MUTEX(private_lock);\
+RTE_DEFINE_MUTEX(private_lock)
+
+/**
+ * Thread mutex representation.
+ */
+typedef struct rte_thread_mutex_tag {
+	void *mutex_id;  /**< mutex identifier */
+} rte_thread_mutex;
+
 /**
  * Returned by rte_thread_barrier_wait() when call is successful.
  */
@@ -314,6 +333,72 @@ __rte_experimental
 int rte_thread_set_priority(rte_thread_t thread_id,
 		enum rte_thread_priority priority);
 
+/**
+ * Initializes a mutex.
+ *
+ * @param mutex
+ *    The mutex to be initialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_init(rte_thread_mutex *mutex);
+
+/**
+ * Locks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be locked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_lock(rte_thread_mutex *mutex);
+
+/**
+ * Unlocks a mutex.
+ *
+ * @param mutex
+ *    The mutex to be unlocked.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_unlock(rte_thread_mutex *mutex);
+
+/**
+ * Tries to lock a mutex.If the mutex is already held by a different thread,
+ * the function returns without blocking.
+ *
+ * @param mutex
+ *    The mutex that will be acquired, if not already locked.
+ *
+ * @return
+ *   On success, if the mutex is acquired, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_try_lock(rte_thread_mutex *mutex);
+
+/**
+ * Releases all resources associated with a mutex.
+ *
+ * @param mutex
+ *    The mutex to be uninitialized.
+ *
+ * @return
+ *   On success, return 0.
+ *   On failure, return a positive errno-style error number.
+ */
+__rte_experimental
+int rte_thread_mutex_destroy(rte_thread_mutex *mutex);
+
 /**
  * Initializes a synchronization barrier.
  *
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 06e5f82da2..e80eea4316 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -431,6 +431,11 @@ EXPERIMENTAL {
 	rte_thread_barrier_wait;
 	rte_thread_barrier_destroy;
 	rte_thread_get_affinity_by_id;
+	rte_thread_mutex_init;
+	rte_thread_mutex_lock;
+	rte_thread_mutex_unlock;
+	rte_thread_mutex_try_lock;
+	rte_thread_mutex_destroy;
 	rte_thread_set_affinity_by_id;
 	rte_thread_get_priority;
 	rte_thread_set_priority;
diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c
index 3f72bbf716..11b4863fe8 100644
--- a/lib/eal/windows/rte_thread.c
+++ b/lib/eal/windows/rte_thread.c
@@ -504,6 +504,70 @@ rte_thread_detach(rte_thread_t thread_id)
 	return 0;
 }
 
+int
+rte_thread_mutex_init(rte_thread_mutex *mutex)
+{
+	int ret = 0;
+	CRITICAL_SECTION *m = NULL;
+
+	RTE_VERIFY(mutex != NULL);
+
+	m = calloc(1, sizeof(*m));
+	if (m == NULL) {
+		RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n");
+		ret = ENOMEM;
+		goto cleanup;
+	}
+
+	InitializeCriticalSection(m);
+	mutex->mutex_id = m;
+	m = NULL;
+
+cleanup:
+	return ret;
+}
+
+int
+rte_thread_mutex_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	EnterCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_unlock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	LeaveCriticalSection(mutex->mutex_id);
+	return 0;
+}
+
+int
+rte_thread_mutex_try_lock(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	if (TryEnterCriticalSection(mutex->mutex_id) != 0)
+		return 0;
+
+	return EBUSY;
+}
+
+int
+rte_thread_mutex_destroy(rte_thread_mutex *mutex)
+{
+	RTE_VERIFY(mutex != NULL);
+
+	DeleteCriticalSection(mutex->mutex_id);
+	free(mutex->mutex_id);
+	mutex->mutex_id = NULL;
+
+	return 0;
+}
+
 int
 rte_thread_barrier_init(rte_thread_barrier *barrier, int count)
 {
-- 
2.31.0.vfs.0.1


^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [PATCH v18 8/8] eal: implement functions for mutex management
  2021-11-11  1:33                                           ` [PATCH v18 8/8] eal: implement functions for mutex management Narcisa Ana Maria Vasile
@ 2021-12-13 20:27                                             ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2021-12-13 20:27 UTC (permalink / raw)
  To: bruce.richardson, stephen, dev, thomas, dmitry.kozliuk, khot,
	navasile, dmitrym, roretzla, talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

On Wed, Nov 10, 2021 at 05:33:45PM -0800, Narcisa Ana Maria Vasile wrote:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Add functions for mutex init, destroy, lock, unlock, trylock.
> 
> Windows does not have a static initializer. Initialization
> is only done through InitializeCriticalSection(). To overcome this,
> RTE_INIT_MUTEX macro is added to replace static initialization
> of mutexes. The macro calls rte_thread_mutex_init().
> 
> Add unit tests to verify that the mutex correctly locks/unlocks
> and protects the data. Check both static and dynamic mutexes.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---

Hi Bruce R., Stephen H., I've followed Bruce's suggestion and changed this patchset
to return ENOTSUP for realtime priority on Linux. Can you please take a look at
the latest version of the patchset?
Let me know if it needs any changes or if it's ready to be merged. Thank you!

^ permalink raw reply	[flat|nested] 290+ messages in thread

* Re: [PATCH v18 1/8] eal: add basic threading functions
  2021-11-11  1:33                                           ` [PATCH v18 1/8] eal: add basic threading functions Narcisa Ana Maria Vasile
@ 2022-04-12 18:00                                             ` Narcisa Ana Maria Vasile
  0 siblings, 0 replies; 290+ messages in thread
From: Narcisa Ana Maria Vasile @ 2022-04-12 18:00 UTC (permalink / raw)
  To: dev, thomas, dmitry.kozliuk, khot, navasile, dmitrym, roretzla,
	talshn, ocardona
  Cc: bruce.richardson, david.marchand, pallavi.kadam

On Wed, Nov 10, 2021 at 05:33:38PM -0800, Narcisa Ana Maria Vasile wrote:
> From: Narcisa Vasile <navasile@microsoft.com>
> 
> Use a portable, type-safe representation for the thread identifier.
> Add functions for comparing thread ids and obtaining the thread id
> for the current thread.
> 
> Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
> ---

Abandoning this patch series.
It is superseded by the thread patches sent by Tyler. 

^ permalink raw reply	[flat|nested] 290+ messages in thread

end of thread, other threads:[~2022-04-12 18:00 UTC | newest]

Thread overview: 290+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-18  1:00 [dpdk-dev] [PATCH 0/3] eal: Add new API for threading Narcisa Ana Maria Vasile
2021-03-18  1:00 ` [dpdk-dev] [PATCH 1/3] Add EAL threads API Narcisa Ana Maria Vasile
2021-03-18 14:48   ` Tal Shnaiderman
2021-03-18 19:42     ` Narcisa Ana Maria Vasile
2021-03-18 20:04     ` Tyler Retzlaff
2021-03-18 15:48   ` David Marchand
2021-03-18 19:40     ` Narcisa Ana Maria Vasile
2021-03-23  0:20   ` [dpdk-dev] [PATCH v2 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-03-23  2:54       ` Stephen Hemminger
2021-03-23 15:53         ` Tyler Retzlaff
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-03-23  0:20     ` [dpdk-dev] [PATCH v2 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-03-25  3:46     ` [dpdk-dev] [PATCH v3 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-03-25  3:46       ` [dpdk-dev] [PATCH v3 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-03-25  3:47       ` [dpdk-dev] [PATCH v3 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-03-26 23:52         ` [dpdk-dev] [PATCH v4 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-03-27 16:04             ` Stephen Hemminger
2021-03-29 22:40             ` [dpdk-dev] [PATCH v5 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-04-03  1:38                 ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading Narcisa Ana Maria Vasile
2021-04-03  1:38                   ` [dpdk-dev] [PATCH v6 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-04-29  0:50                     ` Dmitry Kozlyuk
2021-04-29  7:44                       ` Thomas Monjalon
2021-04-29 12:05                         ` Kinsella, Ray
2021-04-29 16:00                           ` Tyler Retzlaff
2021-04-29 16:28                           ` Dmitry Kozlyuk
2021-04-30  6:37                             ` Narcisa Ana Maria Vasile
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-04-29  0:50                     ` Dmitry Kozlyuk
2021-04-29  7:48                       ` Thomas Monjalon
2021-04-29 15:52                         ` [dpdk-dev] [EXTERNAL] " Tyler Retzlaff
2021-04-30 23:00                           ` Dmitry Kozlyuk
2021-04-29 16:28                         ` [dpdk-dev] " Dmitry Kozlyuk
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-04-29  0:50                     ` Dmitry Kozlyuk
2021-04-30  2:39                       ` Narcisa Ana Maria Vasile
2021-04-30 23:05                         ` Dmitry Kozlyuk
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-05-02  0:41                     ` Dmitry Kozlyuk
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-04-29 20:44                     ` Dmitry Kozlyuk
2021-04-29 21:31                       ` [dpdk-dev] [EXTERNAL] " Dmitry Malloy
2021-04-30 17:22                         ` Dmitry Kozlyuk
2021-04-30 17:51                           ` Dmitry Kozlyuk
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-04-30 17:47                     ` Dmitry Kozlyuk
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-04-30 18:06                     ` Dmitry Kozlyuk
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-04-03  1:39                   ` [dpdk-dev] [PATCH v6 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-04-12  7:56                   ` [dpdk-dev] [PATCH v6 00/10] eal: Add new API for threading David Marchand
2021-04-16 20:30                     ` Narcisa Ana Maria Vasile
2021-06-01 20:55                   ` [dpdk-dev] [PATCH v7 00/10] eal: Add EAL " Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-06-01 20:55                     ` [dpdk-dev] [PATCH v7 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-06-02 15:50                       ` Tal Shnaiderman
2021-06-02 16:16                         ` Narcisa Ana Maria Vasile
2021-06-04 23:38                     ` [dpdk-dev] [PATCH v8 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-06-08 23:04                         ` Dmitry Kozlyuk
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-06-04 23:38                       ` [dpdk-dev] [PATCH v8 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-06-04 23:44                       ` [dpdk-dev] [PATCH v9 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 01/10] eal: add thread id and simple thread functions Narcisa Ana Maria Vasile
2021-06-08 23:03                           ` Dmitry Kozlyuk
2021-06-18 21:30                             ` Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-06-08 23:03                           ` Dmitry Kozlyuk
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-06-08 23:03                           ` Dmitry Kozlyuk
2021-06-18 21:44                             ` Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-06-08 23:04                           ` Dmitry Kozlyuk
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-06-08 23:04                           ` Dmitry Kozlyuk
2021-06-18 21:41                             ` Narcisa Ana Maria Vasile
2021-06-18 22:48                               ` Dmitry Kozlyuk
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-06-08 23:04                           ` Dmitry Kozlyuk
2021-06-09 22:37                             ` Dmitry Kozlyuk
2021-06-12  2:39                               ` Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-06-04 23:44                         ` [dpdk-dev] [PATCH v9 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-06-08  5:50                           ` Narcisa Ana Maria Vasile
2021-06-08  7:45                             ` David Marchand
2021-06-18 21:53                               ` Narcisa Ana Maria Vasile
2021-06-08 23:08                             ` Dmitry Kozlyuk
2021-06-18 21:50                               ` Narcisa Ana Maria Vasile
2021-06-18 21:26                         ` [dpdk-dev] [PATCH v10 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-06-18 21:26                           ` [dpdk-dev] [PATCH v10 9/9] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-07-30 22:31                           ` [dpdk-dev] [PATCH v11 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-07-30 22:31                             ` [dpdk-dev] [PATCH v11 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
2021-08-02 17:32                             ` [dpdk-dev] [PATCH v12 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-08-02 21:08                                 ` Narcisa Ana Maria Vasile
2021-08-02 21:37                                   ` Dmitry Kozlyuk
2021-08-03 15:11                                     ` [dpdk-dev] [dpdk-ci] " Owen Hilyard
2021-08-03 15:38                                       ` Dmitry Kozlyuk
2021-08-03 15:57                                         ` Owen Hilyard
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-08-02 17:32                               ` [dpdk-dev] [PATCH v12 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
2021-08-03 19:01                               ` [dpdk-dev] [PATCH v13 00/10] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 01/10] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 03/10] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-08-15 19:56                                   ` Dmitry Kozlyuk
2021-08-18 21:28                                   ` Stephen Hemminger
2021-08-19  9:06                                     ` Bruce Richardson
2021-08-19 21:30                                       ` Narcisa Ana Maria Vasile
2021-08-19 21:33                                         ` Stephen Hemminger
2021-08-03 19:01                                 ` [dpdk-dev] [PATCH v13 10/10] Add unit tests for thread API Narcisa Ana Maria Vasile
2021-08-19 21:31                                 ` [dpdk-dev] [PATCH v14 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-08-19 21:31                                   ` [dpdk-dev] [PATCH v14 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
2021-08-20 16:10                                     ` Narcisa Ana Maria Vasile
2021-08-20 16:54                                       ` Dmitry Kozlyuk
2021-08-23 20:25                                     ` Dmitry Kozlyuk
2021-10-08 22:40                                   ` [dpdk-dev] [PATCH v15 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-10-08 22:40                                     ` [dpdk-dev] [PATCH v15 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
2021-10-09  7:41                                     ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Narcisa Ana Maria Vasile
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 1/9] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-10-12 16:09                                         ` Thomas Monjalon
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 2/9] eal: add thread attributes Narcisa Ana Maria Vasile
2021-10-12 16:12                                         ` Thomas Monjalon
2021-11-09  1:59                                           ` Narcisa Ana Maria Vasile
2021-11-09  8:27                                             ` Thomas Monjalon
2021-11-10  3:04                                               ` Narcisa Ana Maria Vasile
2021-11-10  3:59                                                 ` Stephen Hemminger
2021-11-10  4:20                                                   ` [EXTERNAL] " Tyler Retzlaff
2021-11-10  6:29                                                     ` [dpdk-dev] [EXTERNAL] " Stephen Hemminger
2021-11-10  9:21                                                       ` Bruce Richardson
2021-11-10 16:52                                                         ` [EXTERNAL] Re: [dpdk-dev] " Tyler Retzlaff
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 3/9] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-10-12 16:16                                         ` Thomas Monjalon
2021-11-09  2:02                                           ` Narcisa Ana Maria Vasile
2021-11-09  8:21                                             ` Thomas Monjalon
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 4/9] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-10-12 16:20                                         ` Thomas Monjalon
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 5/9] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 6/9] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 7/9] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-10-12 16:28                                         ` Thomas Monjalon
2021-11-09  2:04                                           ` Narcisa Ana Maria Vasile
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 8/9] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-10-12 16:32                                         ` Thomas Monjalon
2021-11-09  2:07                                           ` Narcisa Ana Maria Vasile
2021-11-10  3:13                                             ` Narcisa Ana Maria Vasile
2021-10-09  7:41                                       ` [dpdk-dev] [PATCH v16 9/9] Add unit tests for thread API Narcisa Ana Maria Vasile
2021-10-12 16:33                                         ` Thomas Monjalon
2021-11-09  2:10                                           ` Narcisa Ana Maria Vasile
2021-11-09  8:32                                             ` Thomas Monjalon
2021-11-10  3:07                                               ` Narcisa Ana Maria Vasile
2021-10-12 16:07                                       ` [dpdk-dev] [PATCH v16 0/9] eal: Add EAL API for threading Thomas Monjalon
2021-11-09  1:55                                         ` Narcisa Ana Maria Vasile
2021-11-10  3:01                                       ` [dpdk-dev] [PATCH v17 00/13] " Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 01/13] eal: add basic threading functions Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 02/13] eal: add thread attributes Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 03/13] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 04/13] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 05/13] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 06/13] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 07/13] app/test: add unit tests for rte_thread_self Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 08/13] app/test: add unit tests for thread attributes Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 09/13] app/test: add unit tests for thread lifetime management Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 10/13] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 11/13] app/test: add unit tests for barrier Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 12/13] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-11-10  3:01                                         ` [dpdk-dev] [PATCH v17 13/13] app/test: add unit tests for mutex Narcisa Ana Maria Vasile
2021-11-10  9:31                                         ` [dpdk-dev] [PATCH v17 00/13] eal: Add EAL API for threading Thomas Monjalon
2021-11-11  1:33                                         ` [PATCH v18 0/8] " Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 1/8] eal: add basic threading functions Narcisa Ana Maria Vasile
2022-04-12 18:00                                             ` Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 2/8] eal: add thread attributes Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 3/8] eal/windows: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 4/8] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 5/8] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 6/8] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 7/8] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-11-11  1:33                                           ` [PATCH v18 8/8] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-12-13 20:27                                             ` Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 02/10] eal: add thread attributes Narcisa Ana Maria Vasile
2021-03-30 21:14                 ` Stephen Hemminger
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 03/10] windows/eal: translate Windows errors to errno-style errors Narcisa Ana Maria Vasile
2021-03-31 13:56                 ` Tal Shnaiderman
2021-03-31 21:19                   ` Nick Connolly
2021-04-01 12:29                     ` Tal Shnaiderman
2021-04-01 19:07                   ` Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 04/10] eal: implement functions for thread affinity management Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 05/10] eal: implement thread priority management functions Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 06/10] eal: add thread lifetime management Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 07/10] eal: implement functions for mutex management Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 08/10] eal: implement functions for thread barrier management Narcisa Ana Maria Vasile
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 09/10] eal: add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-03-30 21:11                 ` Stephen Hemminger
2021-03-31  8:21                   ` Tal Shnaiderman
2021-03-31 21:12                   ` Dmitry Kozlyuk
2021-03-31 22:09                     ` Stephen Hemminger
2021-03-31 22:42                       ` [dpdk-dev] [EXTERNAL] " Dmitry Malloy
2021-03-29 22:40               ` [dpdk-dev] [PATCH v5 10/10] Enable the new EAL thread API Narcisa Ana Maria Vasile
2021-03-26 23:52           ` [dpdk-dev] [PATCH v4 " Narcisa Ana Maria Vasile
2021-03-18  1:00 ` [dpdk-dev] [PATCH 2/3] Add EAL argument for setting thread priority Narcisa Ana Maria Vasile
2021-03-18  1:00 ` [dpdk-dev] [PATCH 3/3] Enable the new EAL thread API and rename Narcisa Ana Maria Vasile

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).