+
+int
+eal_thread_dump_current_affinity(char *str, unsigned int size)
+{
+ rte_cpuset_t cpuset;
+
+ rte_thread_get_affinity(&cpuset);
+ return eal_thread_dump_affinity(&cpuset, str, size);
+}
+
+void
+__rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset)
+{
+ /* set the lcore ID in per-lcore memory area */
+ RTE_PER_LCORE(_lcore_id) = lcore_id;
+
+ /* acquire system unique id */
+ rte_gettid();
+
+ thread_update_affinity(cpuset);
+
+ __rte_trace_mem_per_thread_alloc();
+}
+
+void
+__rte_thread_uninit(void)
+{
+ trace_mem_per_thread_free();
+
+ RTE_PER_LCORE(_lcore_id) = LCORE_ID_ANY;
+}
+
+struct rte_thread_ctrl_params {
+ void *(*start_routine)(void *);
+ void *arg;
+ pthread_barrier_t configured;
+};
+
+static void *ctrl_thread_init(void *arg)
+{
+ int ret;
+ struct internal_config *internal_conf =
+ eal_get_internal_configuration();
+ rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset;
+ struct rte_thread_ctrl_params *params = arg;
+ void *(*start_routine)(void *) = params->start_routine;
+ void *routine_arg = params->arg;
+
+ __rte_thread_init(rte_lcore_id(), cpuset);
+
+ ret = pthread_barrier_wait(¶ms->configured);
+ if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
+ pthread_barrier_destroy(¶ms->configured);
+ free(params);
+ }
+
+ return start_routine(routine_arg);
+}
+
+int
+rte_ctrl_thread_create(pthread_t *thread, const char *name,
+ const pthread_attr_t *attr,
+ void *(*start_routine)(void *), void *arg)
+{
+ struct internal_config *internal_conf =
+ eal_get_internal_configuration();
+ rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset;
+ struct rte_thread_ctrl_params *params;
+ int ret;
+
+ params = malloc(sizeof(*params));
+ if (!params)
+ return -ENOMEM;
+
+ params->start_routine = start_routine;
+ params->arg = arg;
+
+ pthread_barrier_init(¶ms->configured, NULL, 2);
+
+ ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params);
+ if (ret != 0) {
+ free(params);
+ return -ret;
+ }
+
+ if (name != NULL) {
+ ret = rte_thread_setname(*thread, name);
+ if (ret < 0)
+ RTE_LOG(DEBUG, EAL,
+ "Cannot set name for ctrl thread\n");
+ }
+
+ ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
+ if (ret)
+ goto fail;
+
+ ret = pthread_barrier_wait(¶ms->configured);
+ if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
+ pthread_barrier_destroy(¶ms->configured);
+ free(params);
+ }
+
+ return 0;
+
+fail:
+ if (PTHREAD_BARRIER_SERIAL_THREAD ==
+ pthread_barrier_wait(¶ms->configured)) {
+ pthread_barrier_destroy(¶ms->configured);
+ free(params);
+ }
+ pthread_cancel(*thread);
+ pthread_join(*thread, NULL);
+ return -ret;
+}
+
+int
+rte_thread_register(void)
+{
+ unsigned int lcore_id;
+ rte_cpuset_t cpuset;
+
+ /* EAL init flushes all lcores, we can't register before. */
+ if (eal_get_internal_configuration()->init_complete != 1) {
+ RTE_LOG(DEBUG, EAL, "Called %s before EAL init.\n", __func__);
+ rte_errno = EINVAL;
+ return -1;
+ }
+ if (!rte_mp_disable()) {
+ RTE_LOG(ERR, EAL, "Multiprocess in use, registering non-EAL threads is not supported.\n");
+ rte_errno = EINVAL;
+ return -1;
+ }
+ if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset),
+ &cpuset) != 0)
+ CPU_ZERO(&cpuset);
+ lcore_id = eal_lcore_non_eal_allocate();
+ if (lcore_id >= RTE_MAX_LCORE)
+ lcore_id = LCORE_ID_ANY;
+ __rte_thread_init(lcore_id, &cpuset);
+ if (lcore_id == LCORE_ID_ANY) {
+ rte_errno = ENOMEM;
+ return -1;
+ }
+ RTE_LOG(DEBUG, EAL, "Registered non-EAL thread as lcore %u.\n",
+ lcore_id);
+ return 0;
+}
+
+void
+rte_thread_unregister(void)
+{
+ unsigned int lcore_id = rte_lcore_id();
+
+ if (lcore_id != LCORE_ID_ANY)
+ eal_lcore_non_eal_release(lcore_id);
+ __rte_thread_uninit();
+ if (lcore_id != LCORE_ID_ANY)
+ RTE_LOG(DEBUG, EAL, "Unregistered non-EAL thread (was lcore %u).\n",
+ lcore_id);
+}