@@ -4,6 +4,10 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <odp_posix_extensions.h>
+#include <sched.h>
+#include <pthread.h>
+
#include <odp/init.h>
#include <odp_internal.h>
#include <odp/debug.h>
@@ -11,6 +15,21 @@
struct odp_global_data_s odp_global_data;
+static int init_global_set_affinity(void)
+{
+ int ret;
+ cpu_set_t cpuset;
+
+ CPU_ZERO(&cpuset);
+ CPU_SET(0, &cpuset);
+ ret = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
int odp_init_global(const odp_init_t *params,
const odp_platform_init_t *platform_params ODP_UNUSED)
{
@@ -25,12 +44,6 @@ int odp_init_global(const odp_init_t *params,
odp_global_data.abort_fn = params->abort_fn;
}
- if (odp_time_init_global()) {
- ODP_ERR("ODP time init failed.\n");
- goto init_failed;
- }
- stage = TIME_INIT;
-
if (odp_system_info_init()) {
ODP_ERR("ODP system_info init failed.\n");
goto init_failed;
@@ -91,6 +104,17 @@ int odp_init_global(const odp_init_t *params,
}
stage = CLASSIFICATION_INIT;
+ if (init_global_set_affinity()) {
+ ODP_ERR("ODP affinity init failed.\n");
+ return -1;
+ }
+
+ if (odp_time_init_global()) {
+ ODP_ERR("ODP time init failed.\n");
+ goto init_failed;
+ }
+ stage = TIME_INIT;
+
return 0;
init_failed:
@@ -110,6 +134,13 @@ int _odp_term_global(enum init_stage stage)
switch (stage) {
case ALL_INIT:
+ case TIME_INIT:
+ if (odp_time_term_global()) {
+ ODP_ERR("ODP time term failed.\n");
+ rc = -1;
+ }
+ /* Fall through */
+
case CLASSIFICATION_INIT:
if (odp_classification_term_global()) {
ODP_ERR("ODP classificatio term failed.\n");
@@ -180,13 +211,6 @@ int _odp_term_global(enum init_stage stage)
}
/* Fall through */
- case TIME_INIT:
- if (odp_time_term_global()) {
- ODP_ERR("ODP time term failed.\n");
- rc = -1;
- }
- /* Fall through */
-
case NO_INIT:
;
}
By default it's supposed CPU0 to be used for control thread. So assign CPU0 as control thread CPU. The CPU0 is still can be used for worker threads, but after this change control thread cannot use CPUs used by "worker" threads. As example, in some cases, can happen, at application initialization, the OS scheduler switches control thread on CPUn (n != 0), and if in this time odp timer is scheduled, it executes notify routine on CPUn, which will consume CPU time off some "worker thread" even after initialization. Also this is good example, how control thread should be used, it always runs on same CPU, allowing to use local time API, which can be legal only on single CPU threads. Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> --- platform/linux-generic/odp_init.c | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 13 deletions(-)