/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2021 Mellanox Technologies, Ltd * Copyright (C) 2022 Microsoft Corporation */ #include #include #include #ifndef _RTE_THREAD_H_ #define _RTE_THREAD_H_ /** * @file * * Threading functions * * Simple threads functionality supplied by EAL. */ #ifdef __cplusplus extern "C" { #endif /** Maximum thread name length (including '\0'). */ #define RTE_THREAD_NAME_SIZE 16 /* Old definition, aliased for compatibility. */ #define RTE_MAX_THREAD_NAME_LEN RTE_THREAD_NAME_SIZE /** Thread name prefix automatically added to all internal threads. */ #define RTE_THREAD_INTERNAL_PREFIX "dpdk-" /** Maximum internal thread name length (including '\0'). */ #define RTE_THREAD_INTERNAL_NAME_SIZE 11 /** * Thread id descriptor. */ typedef struct { uintptr_t opaque_id; /**< thread identifier */ } rte_thread_t; /** * Thread function * * Function pointer to thread start routine. * * @param arg * Argument passed to rte_thread_create(). * @return * Thread function exit value. */ typedef uint32_t (*rte_thread_func) (void *arg); /** * 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 */ }; /** * Representation for thread attributes. */ typedef struct { enum rte_thread_priority priority; /**< thread priority */ #ifdef RTE_HAS_CPUSET rte_cpuset_t cpuset; /**< thread affinity */ #endif } rte_thread_attr_t; /** * TLS key type, an opaque pointer. */ typedef struct eal_tls_key *rte_thread_key; /** * 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 arg * Argument to be passed to the 'thread_func' routine. * * @return * On success, return 0. * On failure, return a positive errno-style error number. */ int rte_thread_create(rte_thread_t *thread_id, const rte_thread_attr_t *thread_attr, rte_thread_func thread_func, void *arg); /** * Create a control thread. * * Creates a control thread with the given name and attributes. The * affinity of the new thread is based on the CPU affinity retrieved * at the time rte_eal_init() was called, the EAL threads are then * excluded. If setting the name of the thread fails, the error is * ignored and a debug message is logged. * * @param thread * Filled with the thread id of the new created thread. * @param name * The name of the control thread * (max RTE_THREAD_NAME_SIZE characters including '\0'). * @param thread_func * Function to be executed by the new thread. * @param arg * Argument passed to thread_func. * @return * On success, returns 0; on error, it returns a negative value * corresponding to the error number. */ int rte_thread_create_control(rte_thread_t *thread, const char *name, rte_thread_func thread_func, void *arg); /** * Create an internal control thread. * * Creates a control thread with the given name prefixed. * If setting the name of the thread fails, the error is ignored and logged. * * The affinity of the new thread is based on the CPU affinity retrieved * at the time rte_eal_init() was called, the EAL threads are then excluded. * * @param id * Filled with the thread ID of the new created thread. * @param name * The name of the control thread. * See RTE_THREAD_INTERNAL_NAME_SIZE for maximum length. * The name of the driver or library should be first, * then followed by a hyphen and more details. * It will be prefixed with RTE_THREAD_INTERNAL_PREFIX by this function. * @param func * Function to be executed by the new thread. * @param arg * Argument passed to func. * @return * On success, returns 0; a negative value otherwise. */ __rte_internal int rte_thread_create_internal_control(rte_thread_t *id, const char *name, rte_thread_func func, void *arg); /** * 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. */ int rte_thread_join(rte_thread_t thread_id, uint32_t *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. */ int rte_thread_detach(rte_thread_t thread_id); /** * Get the id of the calling thread. * * @return * Return the thread id of the calling thread. */ rte_thread_t rte_thread_self(void); /** * Set the name of the thread. * * This API is a noop if the underlying platform does not * support setting the thread name or the platform-specific * API used to set the thread name fails. * * @param thread_id * The id of the thread to set name. * * @param thread_name * The name to set. Truncated to RTE_THREAD_NAME_SIZE, * including terminating NUL if necessary. */ void rte_thread_set_name(rte_thread_t thread_id, const char *thread_name); /** * Set the name of an internal thread with the common prefix. * * This API is a noop if the underlying platform does not support * setting the thread name, or if it fails. * * @param id * The ID of the thread to set name. * * @param name * The name to set after being prefixed. * See RTE_THREAD_INTERNAL_NAME_SIZE for maximum length. * The name of the driver or library should be first, * then followed by a hyphen and more details. * It will be prefixed with RTE_THREAD_INTERNAL_PREFIX by this function. */ __rte_internal void rte_thread_set_prefixed_name(rte_thread_t id, const char *name); /** * 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. */ 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. */ int rte_thread_attr_init(rte_thread_attr_t *attr); /** * 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. */ int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr, enum rte_thread_priority priority); #ifdef RTE_HAS_CPUSET /** * 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. */ 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. */ int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr, rte_cpuset_t *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. */ 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. */ int rte_thread_get_affinity_by_id(rte_thread_t thread_id, rte_cpuset_t *cpuset); /** * 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 */ /** * 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. */ 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. */ 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. * and optional destructor can be set to be called when a thread exits. * * @param key * Pointer to store the allocated key. * @param destructor * The function to be called when the thread exits. * Ignored on Windows OS. * * @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. */ int rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *)); /** * Delete a TLS data key visible to all threads in the process. * * @param key * The key allocated by rte_thread_key_create(). * * @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. */ int rte_thread_key_delete(rte_thread_key key); /** * Set value bound to the TLS key on behalf of the calling thread. * * @param key * The key allocated by rte_thread_key_create(). * @param value * The value bound to the rte_thread_key key for the calling thread. * * @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. */ int rte_thread_value_set(rte_thread_key key, const void *value); /** * Get value bound to the TLS key on behalf of the calling thread. * * @param key * The key allocated by rte_thread_key_create(). * * @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. */ void *rte_thread_value_get(rte_thread_key key); #ifdef __cplusplus } #endif #endif /* _RTE_THREAD_H_ */