Message ID | 20161223191541.31493-4-mike.holmes@linaro.org |
---|---|
State | New |
Headers | show |
On 2016-12-23 14:15, Mike Holmes wrote: > Only the portable api is built by default, use --enable-helper-extn > to enable non portable APIs for a helper platform > > Signed-off-by: Mike Holmes <mike.holmes@linaro.org> > --- Got the following warning when applying this patch: Applying: helper: move thread implementation under platform .git/rebase-apply/patch:671: indent with spaces. @with_helper_platform@/process$(EXEEXT) warning: 1 line adds whitespace errors. > configure.ac | 17 +- > example/Makefile.inc | 2 +- > helper/Makefile.am | 15 +- > .../helper/platform/linux-generic/threads_extn.h | 112 ++++++++ > helper/include/odp/helper/threads.h | 76 ----- > helper/m4/configure.m4 | 11 + > helper/odph_thread_internal.h | 27 ++ > helper/platform/linux-generic/thread.c | 256 +++++++++++++++++ > helper/test/Makefile.am | 17 +- > helper/test/linux-generic/Makefile.am | 5 + > helper/test/{ => linux-generic}/process.c | 2 +- > helper/test/{ => linux-generic}/thread.c | 2 +- > helper/threads.c | 314 ++++----------------- > ...inux.pc.in => libodphelper-linux-generic.pc.in} | 4 +- > test/Makefile.inc | 2 +- > test/common_plat/validation/api/Makefile.inc | 2 +- > test/linux-generic/Makefile.inc | 2 +- > 17 files changed, 515 insertions(+), 351 deletions(-) > create mode 100644 helper/include/odp/helper/platform/linux-generic/threads_extn.h > create mode 100644 helper/odph_thread_internal.h > create mode 100644 helper/platform/linux-generic/thread.c > create mode 100644 helper/test/linux-generic/Makefile.am > rename helper/test/{ => linux-generic}/process.c (97%) > rename helper/test/{ => linux-generic}/thread.c (97%) > rename pkgconfig/{libodphelper-linux.pc.in => libodphelper-linux-generic.pc.in} (72%) > > diff --git a/configure.ac b/configure.ac > index 4fec9d5..001cab9 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -138,6 +138,18 @@ AC_SUBST([with_platform]) > AC_SUBST([platform_with_platform], ["platform/${with_platform}"]) > > ########################################################################## > +# Determine which helper platform to build for > +########################################################################## > +AC_ARG_WITH([helper_platform], > + [AS_HELP_STRING([--with-helper_platform=platform], > + [select helper platform to be used, default linux-generic])], > + [], > + [with_helper_platform=${with_platform} > + ]) > + > +AC_SUBST([with_helper_platform]) > + > +########################################################################## > # Run platform specific checks and settings > ########################################################################## > IMPLEMENTATION_NAME="" > @@ -202,6 +214,7 @@ AM_CONDITIONAL([test_example], [test x$test_example = xyes ]) > AM_CONDITIONAL([HAVE_DOXYGEN], [test "x${DOXYGEN}" = "xdoxygen"]) > AM_CONDITIONAL([user_guide], [test "x${user_guides}" = "xyes" ]) > AM_CONDITIONAL([HAVE_MSCGEN], [test "x${MSCGEN}" = "xmscgen"]) > +AM_CONDITIONAL([helper_ext], [test x$helper_ext = xyes ]) > > ########################################################################## > # Setup doxygen documentation > @@ -293,7 +306,7 @@ AM_CXXFLAGS="-std=c++11" > > AC_CONFIG_FILES([Makefile > pkgconfig/libodp-linux.pc > - pkgconfig/libodphelper-linux.pc > + pkgconfig/libodphelper-linux-generic.pc > ]) > > AC_SEARCH_LIBS([timer_create],[rt posix4]) > @@ -320,6 +333,8 @@ AC_MSG_RESULT([ > implementation_name: ${IMPLEMENTATION_NAME} > ARCH_DIR ${ARCH_DIR} > with_platform: ${with_platform} > + with_helper_platform: ${with_helper_platform} > + helper_ext: ${helper_ext} > prefix: ${prefix} > sysconfdir: ${sysconfdir} > libdir: ${libdir} > diff --git a/example/Makefile.inc b/example/Makefile.inc > index 19d3994..ea596d5 100644 > --- a/example/Makefile.inc > +++ b/example/Makefile.inc > @@ -1,6 +1,6 @@ > include $(top_srcdir)/platform/@with_platform@/Makefile.inc > LIB = $(top_builddir)/lib > -LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper-linux.la > +LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper-@with_helper_platform@.la > AM_CFLAGS += \ > -I$(srcdir) \ > -I$(top_srcdir)/example \ > diff --git a/helper/Makefile.am b/helper/Makefile.am > index 71c6975..66d60dd 100644 > --- a/helper/Makefile.am > +++ b/helper/Makefile.am > @@ -1,7 +1,7 @@ > include $(top_srcdir)/platform/@with_platform@/Makefile.inc > > pkgconfigdir = $(libdir)/pkgconfig > -pkgconfig_DATA = $(top_builddir)/pkgconfig/libodphelper-linux.pc > +pkgconfig_DATA = $(top_builddir)/pkgconfig/libodphelper-@with_helper_platform@.pc > > LIB = $(top_builddir)/lib > AM_CFLAGS = -I$(srcdir)/include > @@ -25,18 +25,25 @@ helperinclude_HEADERS = \ > $(srcdir)/include/odp/helper/table.h\ > $(srcdir)/include/odp/helper/udp.h > > +if helper_ext > +helperinclude_HEADERS += \ > + $(srcdir)/include/odp/helper/platform/@with_helper_platform@/threads_extn.h > +endif > + > noinst_HEADERS = \ > $(srcdir)/odph_debug.h \ > $(srcdir)/odph_hashtable.h \ > $(srcdir)/odph_lineartable.h \ > - $(srcdir)/odph_list_internal.h > + $(srcdir)/odph_list_internal.h \ > + $(srcdir)/odph_thread_internal.h > > -__LIB__libodphelper_linux_la_SOURCES = \ > +__LIB__libodphelper_@with_helper_platform@_la_SOURCES = \ > eth.c \ > ip.c \ > chksum.c \ > threads.c \ > + platform/@with_helper_platform@/thread.c \ > hashtable.c \ > lineartable.c > > -lib_LTLIBRARIES = $(LIB)/libodphelper-linux.la > +lib_LTLIBRARIES = $(LIB)/libodphelper-@with_helper_platform@.la > diff --git a/helper/include/odp/helper/platform/linux-generic/threads_extn.h b/helper/include/odp/helper/platform/linux-generic/threads_extn.h > new file mode 100644 > index 0000000..1d4036d > --- /dev/null > +++ b/helper/include/odp/helper/platform/linux-generic/threads_extn.h > @@ -0,0 +1,112 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP Linux helper extension API > + * > + * This file is an optional helper to odp.h APIs. These functions are provided > + * to ease common setups in a Linux system. User is free to implement the same > + * setups in otherways (not via this API). > + */ > + > +#ifndef ODPH_LINUX_EXT_H_ > +#define ODPH_LINUX_EXT_H_ > + > +#include <odp/helper/threads.h> > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** @addtogroup odph_linux ODPH LINUX > + * @{ > + */ > + > +/** > + * Creates and launches pthreads > + * > + * Creates, pins and launches threads to separate CPU's based on the cpumask. > + * > + * @param[out] pthread_tbl Table of pthread state information records. Table > + * must have at least as many entries as there are > + * CPUs in the CPU mask. > + * @param mask CPU mask > + * @param thr_params Linux helper thread parameters > + * > + * @return Number of threads created > + */ > +int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params); > + > +/** > + * Waits pthreads to exit > + * > + * Returns when all threads have been exit. > + * > + * @param thread_tbl Thread table > + * @param num Number of threads to create > + * > + */ > +void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num); > + > +/** > + * Fork a process > + * > + * Forks and sets CPU affinity for the child process. Ignores 'start' and 'arg' > + * thread parameters. > + * > + * @param[out] proc Pointer to process state info (for output) > + * @param cpu Destination CPU for the child process > + * @param thr_params Linux helper thread parameters > + * > + * @return On success: 1 for the parent, 0 for the child > + * On failure: -1 for the parent, -2 for the child > + */ > +int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > + const odph_linux_thr_params_t *thr_params); > + > +/** > + * Fork a number of processes > + * > + * Forks and sets CPU affinity for child processes. Ignores 'start' and 'arg' > + * thread parameters. > + * > + * @param[out] proc_tbl Process state info table (for output) > + * @param mask CPU mask of processes to create > + * @param thr_params Linux helper thread parameters > + * > + * @return On success: 1 for the parent, 0 for the child > + * On failure: -1 for the parent, -2 for the child > + */ > +int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params); > + > +/** > + * Wait for a number of processes > + * > + * Waits for a number of child processes to terminate. Records process state > + * change status into the process state info structure. > + * > + * @param proc_tbl Process state info table (previously filled by fork) > + * @param num Number of processes to wait > + * > + * @return 0 on success, -1 on failure > + */ > +int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num); > + > +/** > + * @} > + */ > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/helper/include/odp/helper/threads.h b/helper/include/odp/helper/threads.h > index b8d975a..5682bab 100644 > --- a/helper/include/odp/helper/threads.h > +++ b/helper/include/odp/helper/threads.h > @@ -93,82 +93,6 @@ typedef struct { > } odph_odpthread_t; > > /** > - * Creates and launches pthreads > - * > - * Creates, pins and launches threads to separate CPU's based on the cpumask. > - * > - * @param[out] pthread_tbl Table of pthread state information records. Table > - * must have at least as many entries as there are > - * CPUs in the CPU mask. > - * @param mask CPU mask > - * @param thr_params Linux helper thread parameters > - * > - * @return Number of threads created > - */ > -int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params); > - > -/** > - * Waits pthreads to exit > - * > - * Returns when all threads have been exit. > - * > - * @param thread_tbl Thread table > - * @param num Number of threads to create > - * > - */ > -void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num); > - > -/** > - * Fork a process > - * > - * Forks and sets CPU affinity for the child process. Ignores 'start' and 'arg' > - * thread parameters. > - * > - * @param[out] proc Pointer to process state info (for output) > - * @param cpu Destination CPU for the child process > - * @param thr_params Linux helper thread parameters > - * > - * @return On success: 1 for the parent, 0 for the child > - * On failure: -1 for the parent, -2 for the child > - */ > -int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > - const odph_linux_thr_params_t *thr_params); > - > - > -/** > - * Fork a number of processes > - * > - * Forks and sets CPU affinity for child processes. Ignores 'start' and 'arg' > - * thread parameters. > - * > - * @param[out] proc_tbl Process state info table (for output) > - * @param mask CPU mask of processes to create > - * @param thr_params Linux helper thread parameters > - * > - * @return On success: 1 for the parent, 0 for the child > - * On failure: -1 for the parent, -2 for the child > - */ > -int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params); > - > - > -/** > - * Wait for a number of processes > - * > - * Waits for a number of child processes to terminate. Records process state > - * change status into the process state info structure. > - * > - * @param proc_tbl Process state info table (previously filled by fork) > - * @param num Number of processes to wait > - * > - * @return 0 on success, -1 on failure > - */ > -int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num); > - > -/** > * Creates and launches odpthreads (as linux threads or processes) > * > * Creates, pins and launches threads to separate CPU's based on the cpumask. > diff --git a/helper/m4/configure.m4 b/helper/m4/configure.m4 > index b8a21f7..8f1c929 100644 > --- a/helper/m4/configure.m4 > +++ b/helper/m4/configure.m4 > @@ -8,5 +8,16 @@ AC_ARG_ENABLE([test-helper], > test_helper=yes > fi]) > > +########################################################################## > +# Enable/disable helper-ext > +# platform specific non portable extensions > +########################################################################## > +helper_ext=no > +AC_ARG_ENABLE([helper-ext], > + [ --enable-helper-ext build helper platform extensions (not portable)], > + [if test "x$enableval" = "xyes"; then > + helper_ext=yes > + fi]) > + > AC_CONFIG_FILES([helper/Makefile > helper/test/Makefile]) > diff --git a/helper/odph_thread_internal.h b/helper/odph_thread_internal.h > new file mode 100644 > index 0000000..24d5e09 > --- /dev/null > +++ b/helper/odph_thread_internal.h > @@ -0,0 +1,27 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP Helper internal thread APIs > + */ > + > +#ifndef ODPH_THREAD_INTERNAL_H_ > +#define ODPH_THREAD_INTERNAL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +void *_odph_run_start_routine(void *arg); > +void *_odph_thread_run_start_routine(void *arg); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/helper/platform/linux-generic/thread.c b/helper/platform/linux-generic/thread.c > new file mode 100644 > index 0000000..b6424a7 > --- /dev/null > +++ b/helper/platform/linux-generic/thread.c > @@ -0,0 +1,256 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef _GNU_SOURCE > +#define _GNU_SOURCE > +#endif > +#include <sched.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <sys/prctl.h> > +#include <sys/syscall.h> > + > +#include <stdlib.h> > +#include <string.h> > +#include <stdio.h> > +#include <stdbool.h> > + > +#include <odp_api.h> > +#include <odp/helper/platform/linux-generic/threads_extn.h> > +#include <odph_thread_internal.h> > +#include "odph_debug.h" > + > +int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params) > +{ > + int i; > + int num; > + int cpu_count; > + int cpu; > + int ret; > + > + num = odp_cpumask_count(mask); > + > + memset(pthread_tbl, 0, num * sizeof(odph_linux_pthread_t)); > + > + cpu_count = odp_cpu_count(); > + > + if (num < 1 || num > cpu_count) { > + ODPH_ERR("Invalid number of threads:%d (%d cores available)\n", > + num, cpu_count); > + return 0; > + } > + > + cpu = odp_cpumask_first(mask); > + for (i = 0; i < num; i++) { > + cpu_set_t cpu_set; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + pthread_attr_init(&pthread_tbl[i].attr); > + > + pthread_tbl[i].cpu = cpu; > + > + pthread_attr_setaffinity_np(&pthread_tbl[i].attr, > + sizeof(cpu_set_t), &cpu_set); > + > + pthread_tbl[i].thr_params.start = thr_params->start; > + pthread_tbl[i].thr_params.arg = thr_params->arg; > + pthread_tbl[i].thr_params.thr_type = thr_params->thr_type; > + pthread_tbl[i].thr_params.instance = thr_params->instance; > + > + ret = pthread_create(&pthread_tbl[i].thread, > + &pthread_tbl[i].attr, > + _odph_run_start_routine, > + &pthread_tbl[i].thr_params); > + if (ret != 0) { > + ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > + break; > + } > + > + cpu = odp_cpumask_next(mask, cpu); > + } > + > + return i; > +} > + > +void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num) > +{ > + int i; > + int ret; > + > + for (i = 0; i < num; i++) { > + /* Wait thread to exit */ > + ret = pthread_join(thread_tbl[i].thread, NULL); > + if (ret != 0) { > + ODPH_ERR("Failed to join thread from cpu #%d\n", > + thread_tbl[i].cpu); > + } > + pthread_attr_destroy(&thread_tbl[i].attr); > + } > +} > + > +int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params) > +{ > + pid_t pid; > + int num; > + int cpu_count; > + int cpu; > + int i; > + > + num = odp_cpumask_count(mask); > + > + memset(proc_tbl, 0, num * sizeof(odph_linux_process_t)); > + > + cpu_count = odp_cpu_count(); > + > + if (num < 1 || num > cpu_count) { > + ODPH_ERR("Bad num\n"); > + return -1; > + } > + > + cpu = odp_cpumask_first(mask); > + for (i = 0; i < num; i++) { > + cpu_set_t cpu_set; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + pid = fork(); > + > + if (pid < 0) { > + ODPH_ERR("fork() failed\n"); > + return -1; > + } > + > + /* Parent continues to fork */ > + if (pid > 0) { > + proc_tbl[i].pid = pid; > + proc_tbl[i].cpu = cpu; > + > + cpu = odp_cpumask_next(mask, cpu); > + continue; > + } > + > + /* Child process */ > + > + /* Request SIGTERM if parent dies */ > + prctl(PR_SET_PDEATHSIG, SIGTERM); > + /* Parent died already? */ > + if (getppid() == 1) > + kill(getpid(), SIGTERM); > + > + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > + ODPH_ERR("sched_setaffinity() failed\n"); > + return -2; > + } > + > + if (odp_init_local(thr_params->instance, > + thr_params->thr_type)) { > + ODPH_ERR("Local init failed\n"); > + return -2; > + } > + > + return 0; > + } > + > + return 1; > +} > + > +int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > + const odph_linux_thr_params_t *thr_params) > +{ > + odp_cpumask_t mask; > + > + odp_cpumask_zero(&mask); > + odp_cpumask_set(&mask, cpu); > + return odph_linux_process_fork_n(proc, &mask, thr_params); > +} > + > +int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num) > +{ > + pid_t pid; > + int i, j; > + int status = 0; > + > + for (i = 0; i < num; i++) { > + pid = wait(&status); > + > + if (pid < 0) { > + ODPH_ERR("wait() failed\n"); > + return -1; > + } > + > + for (j = 0; j < num; j++) { > + if (proc_tbl[j].pid == pid) { > + proc_tbl[j].status = status; > + break; > + } > + } > + > + if (j == num) { > + ODPH_ERR("Bad pid:%d\n", (int)pid); > + return -1; > + } > + > + /* Examine the child process' termination status */ > + if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) { > + ODPH_ERR("Child exit status:%d (pid:%d)\n", > + WEXITSTATUS(status), (int)pid); > + return -1; > + } > + if (WIFSIGNALED(status)) { > + int signo = WTERMSIG(status); > + > + ODPH_ERR("Child term signo:%d - %s (pid:%d)\n", > + signo, strsignal(signo), (int)pid); > + return -1; > + } > + } > + > + return 0; > +} > + > +/* > + * Create a single ODPthread as a linux thread > + */ > +static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, > + int cpu, > + const odph_odpthread_params_t *thr_params) > +{ > + int ret; > + cpu_set_t cpu_set; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + pthread_attr_init(&thread_tbl->thread.attr); > + > + thread_tbl->cpu = cpu; > + > + pthread_attr_setaffinity_np(&thread_tbl->thread.attr, > + sizeof(cpu_set_t), &cpu_set); > + > + thread_tbl->start_args.thr_params = *thr_params; /* copy */ > + thread_tbl->start_args.linuxtype = ODPTHREAD_PTHREAD; > + > + ret = pthread_create(&thread_tbl->thread.thread_id, > + &thread_tbl->thread.attr, > + _odph_thread_run_start_routine, > + &thread_tbl->start_args); > + if (ret != 0) { > + ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > + thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; > + return ret; > + } > + > + return 0; > +} > diff --git a/helper/test/Makefile.am b/helper/test/Makefile.am > index 545db73..47dcb86 100644 > --- a/helper/test/Makefile.am > +++ b/helper/test/Makefile.am > @@ -6,11 +6,18 @@ AM_LDFLAGS += -static > TESTS_ENVIRONMENT += TEST_DIR=${builddir} > > EXECUTABLES = chksum$(EXEEXT) \ > - thread$(EXEEXT) \ > parse$(EXEEXT)\ > - process$(EXEEXT)\ > table$(EXEEXT) > > +#These are platform specific extensions that are not portable > +#They are a convenience to app writers who have chosen to > +#restrict their application to Linux. > + > +if helper_ext > +EXECUTABLES += @with_helper_platform@/thread$(EXEEXT) \ > + @with_helper_platform@/process$(EXEEXT) > +endif > + > COMPILE_ONLY = odpthreads > > TESTSCRIPTS = odpthreads_as_processes \ > @@ -28,10 +35,6 @@ EXTRA_DIST = odpthreads_as_processes odpthreads_as_pthreads > > dist_chksum_SOURCES = chksum.c > dist_odpthreads_SOURCES = odpthreads.c > -odpthreads_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > -dist_thread_SOURCES = thread.c > -thread_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > -dist_process_SOURCES = process.c > +odpthreads_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > dist_parse_SOURCES = parse.c > -process_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > dist_table_SOURCES = table.c > diff --git a/helper/test/linux-generic/Makefile.am b/helper/test/linux-generic/Makefile.am > new file mode 100644 > index 0000000..28d54a8 > --- /dev/null > +++ b/helper/test/linux-generic/Makefile.am > @@ -0,0 +1,5 @@ > + > +thread_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > +dist_thread_SOURCES = thread.c > +dist_process_SOURCES = process.c > +process_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > diff --git a/helper/test/process.c b/helper/test/linux-generic/process.c > similarity index 97% > rename from helper/test/process.c > rename to helper/test/linux-generic/process.c > index f3c6d50..f641128 100644 > --- a/helper/test/process.c > +++ b/helper/test/linux-generic/process.c > @@ -6,7 +6,7 @@ > > #include <test_debug.h> > #include <odp_api.h> > -#include <odp/helper/threads.h> > +#include <odp/helper/platform/linux-generic/threads_extn.h> > > #define NUMBER_WORKERS 16 /* 0 = max */ > > diff --git a/helper/test/thread.c b/helper/test/linux-generic/thread.c > similarity index 97% > rename from helper/test/thread.c > rename to helper/test/linux-generic/thread.c > index da94b49..f1ca1b7 100644 > --- a/helper/test/thread.c > +++ b/helper/test/linux-generic/thread.c > @@ -6,7 +6,7 @@ > > #include <test_debug.h> > #include <odp_api.h> > -#include <odp/helper/threads.h> > +#include <odp/helper/platform/linux-generic/threads_extn.h> > > #define NUMBER_WORKERS 16 > static void *worker_fn(void *arg TEST_UNUSED) > diff --git a/helper/threads.c b/helper/threads.c > index d5215c2..edfbe0e 100644 > --- a/helper/threads.c > +++ b/helper/threads.c > @@ -9,25 +9,24 @@ > #endif > #include <sched.h> > #include <unistd.h> > -#include <sys/types.h> > #include <sys/wait.h> > #include <sys/prctl.h> > #include <sys/syscall.h> > > -#include <stdlib.h> > -#include <string.h> > -#include <stdio.h> > -#include <stdbool.h> > - > #include <odp_api.h> > #include <odp/helper/threads.h> > #include "odph_debug.h" > > +static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, > + int cpu, > + const odph_odpthread_params_t *thr_params > + ); > + > static struct { > int proc; /* true when process mode is required, false otherwise */ > } helper_options; > > -static void *odp_run_start_routine(void *arg) > +void *_odph_run_start_routine(void *arg) > { > odph_linux_thr_params_t *thr_params = arg; > > @@ -48,206 +47,11 @@ static void *odp_run_start_routine(void *arg) > return ret_ptr; > } > > -int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params) > -{ > - int i; > - int num; > - int cpu_count; > - int cpu; > - int ret; > - > - num = odp_cpumask_count(mask); > - > - memset(pthread_tbl, 0, num * sizeof(odph_linux_pthread_t)); > - > - cpu_count = odp_cpu_count(); > - > - if (num < 1 || num > cpu_count) { > - ODPH_ERR("Invalid number of threads:%d (%d cores available)\n", > - num, cpu_count); > - return 0; > - } > - > - cpu = odp_cpumask_first(mask); > - for (i = 0; i < num; i++) { > - cpu_set_t cpu_set; > - > - CPU_ZERO(&cpu_set); > - CPU_SET(cpu, &cpu_set); > - > - pthread_attr_init(&pthread_tbl[i].attr); > - > - pthread_tbl[i].cpu = cpu; > - > - pthread_attr_setaffinity_np(&pthread_tbl[i].attr, > - sizeof(cpu_set_t), &cpu_set); > - > - pthread_tbl[i].thr_params.start = thr_params->start; > - pthread_tbl[i].thr_params.arg = thr_params->arg; > - pthread_tbl[i].thr_params.thr_type = thr_params->thr_type; > - pthread_tbl[i].thr_params.instance = thr_params->instance; > - > - ret = pthread_create(&pthread_tbl[i].thread, > - &pthread_tbl[i].attr, > - odp_run_start_routine, > - &pthread_tbl[i].thr_params); > - if (ret != 0) { > - ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > - break; > - } > - > - cpu = odp_cpumask_next(mask, cpu); > - } > - > - return i; > -} > - > -void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num) > -{ > - int i; > - int ret; > - > - for (i = 0; i < num; i++) { > - /* Wait thread to exit */ > - ret = pthread_join(thread_tbl[i].thread, NULL); > - if (ret != 0) { > - ODPH_ERR("Failed to join thread from cpu #%d\n", > - thread_tbl[i].cpu); > - } > - pthread_attr_destroy(&thread_tbl[i].attr); > - } > -} > - > -int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params) > -{ > - pid_t pid; > - int num; > - int cpu_count; > - int cpu; > - int i; > - > - num = odp_cpumask_count(mask); > - > - memset(proc_tbl, 0, num * sizeof(odph_linux_process_t)); > - > - cpu_count = odp_cpu_count(); > - > - if (num < 1 || num > cpu_count) { > - ODPH_ERR("Bad num\n"); > - return -1; > - } > - > - cpu = odp_cpumask_first(mask); > - for (i = 0; i < num; i++) { > - cpu_set_t cpu_set; > - > - CPU_ZERO(&cpu_set); > - CPU_SET(cpu, &cpu_set); > - > - pid = fork(); > - > - if (pid < 0) { > - ODPH_ERR("fork() failed\n"); > - return -1; > - } > - > - /* Parent continues to fork */ > - if (pid > 0) { > - proc_tbl[i].pid = pid; > - proc_tbl[i].cpu = cpu; > - > - cpu = odp_cpumask_next(mask, cpu); > - continue; > - } > - > - /* Child process */ > - > - /* Request SIGTERM if parent dies */ > - prctl(PR_SET_PDEATHSIG, SIGTERM); > - /* Parent died already? */ > - if (getppid() == 1) > - kill(getpid(), SIGTERM); > - > - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > - ODPH_ERR("sched_setaffinity() failed\n"); > - return -2; > - } > - > - if (odp_init_local(thr_params->instance, > - thr_params->thr_type)) { > - ODPH_ERR("Local init failed\n"); > - return -2; > - } > - > - return 0; > - } > - > - return 1; > -} > - > -int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > - const odph_linux_thr_params_t *thr_params) > -{ > - odp_cpumask_t mask; > - > - odp_cpumask_zero(&mask); > - odp_cpumask_set(&mask, cpu); > - return odph_linux_process_fork_n(proc, &mask, thr_params); > -} > - > -int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num) > -{ > - pid_t pid; > - int i, j; > - int status = 0; > - > - for (i = 0; i < num; i++) { > - pid = wait(&status); > - > - if (pid < 0) { > - ODPH_ERR("wait() failed\n"); > - return -1; > - } > - > - for (j = 0; j < num; j++) { > - if (proc_tbl[j].pid == pid) { > - proc_tbl[j].status = status; > - break; > - } > - } > - > - if (j == num) { > - ODPH_ERR("Bad pid:%d\n", (int)pid); > - return -1; > - } > - > - /* Examine the child process' termination status */ > - if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) { > - ODPH_ERR("Child exit status:%d (pid:%d)\n", > - WEXITSTATUS(status), (int)pid); > - return -1; > - } > - if (WIFSIGNALED(status)) { > - int signo = WTERMSIG(status); > - > - ODPH_ERR("Child term signo:%d - %s (pid:%d)\n", > - signo, strsignal(signo), (int)pid); > - return -1; > - } > - } > - > - return 0; > -} > - > /* > * wrapper for odpthreads, either implemented as linux threads or processes. > * (in process mode, if start_routine returns NULL, the process return FAILURE). > */ > -static void *odpthread_run_start_routine(void *arg) > +void *_odph_thread_run_start_routine(void *arg) > { > int status; > int ret; > @@ -289,54 +93,6 @@ static void *odpthread_run_start_routine(void *arg) > } > > /* > - * Create a single ODPthread as a linux process > - */ > -static int odph_linux_process_create(odph_odpthread_t *thread_tbl, > - int cpu, > - const odph_odpthread_params_t *thr_params) > -{ > - cpu_set_t cpu_set; > - pid_t pid; > - > - CPU_ZERO(&cpu_set); > - CPU_SET(cpu, &cpu_set); > - > - thread_tbl->start_args.thr_params = *thr_params; /* copy */ > - thread_tbl->start_args.linuxtype = ODPTHREAD_PROCESS; > - thread_tbl->cpu = cpu; > - > - pid = fork(); > - if (pid < 0) { > - ODPH_ERR("fork() failed\n"); > - thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; > - return -1; > - } > - > - /* Parent continues to fork */ > - if (pid > 0) { > - thread_tbl->proc.pid = pid; > - return 0; > - } > - > - /* Child process */ > - > - /* Request SIGTERM if parent dies */ > - prctl(PR_SET_PDEATHSIG, SIGTERM); > - /* Parent died already? */ > - if (getppid() == 1) > - kill(getpid(), SIGTERM); > - > - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > - ODPH_ERR("sched_setaffinity() failed\n"); > - return -2; > - } > - > - odpthread_run_start_routine(&thread_tbl->start_args); > - > - return 0; /* never reached */ > -} > - > -/* > * Create a single ODPthread as a linux thread > */ > static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, > @@ -361,7 +117,7 @@ static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, > > ret = pthread_create(&thread_tbl->thread.thread_id, > &thread_tbl->thread.attr, > - odpthread_run_start_routine, > + _odph_thread_run_start_routine, > &thread_tbl->start_args); > if (ret != 0) { > ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > @@ -405,9 +161,9 @@ int odph_odpthreads_create(odph_odpthread_t *thread_tbl, > thr_params)) > break; > } else { > - if (odph_linux_process_create(&thread_tbl[i], > - cpu, > - thr_params)) > + if (_odph_linux_process_create(&thread_tbl[i], > + cpu, > + thr_params)) > break; > } > > @@ -677,3 +433,51 @@ int odph_parse_options(int argc, char *argv[], > > return res; > } > + > +/* > + * Create a single ODPthread as a linux process > + */ > +static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, > + int cpu, > + const odph_odpthread_params_t *thr_params) > +{ > + cpu_set_t cpu_set; > + pid_t pid; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + thread_tbl->start_args.thr_params = *thr_params; /* copy */ > + thread_tbl->start_args.linuxtype = ODPTHREAD_PROCESS; > + thread_tbl->cpu = cpu; > + > + pid = fork(); > + if (pid < 0) { > + ODPH_ERR("fork() failed\n"); > + thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; > + return -1; > + } > + > + /* Parent continues to fork */ > + if (pid > 0) { > + thread_tbl->proc.pid = pid; > + return 0; > + } > + > + /* Child process */ > + > + /* Request SIGTERM if parent dies */ > + prctl(PR_SET_PDEATHSIG, SIGTERM); > + /* Parent died already? */ > + if (getppid() == 1) > + kill(getpid(), SIGTERM); > + > + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > + ODPH_ERR("sched_setaffinity() failed\n"); > + return -2; > + } > + > + _odph_thread_run_start_routine(&thread_tbl->start_args); > + > + return 0; /* never reached */ > +} > diff --git a/pkgconfig/libodphelper-linux.pc.in b/pkgconfig/libodphelper-linux-generic.pc.in > similarity index 72% > rename from pkgconfig/libodphelper-linux.pc.in > rename to pkgconfig/libodphelper-linux-generic.pc.in > index 3987f4c..cab7be2 100644 > --- a/pkgconfig/libodphelper-linux.pc.in > +++ b/pkgconfig/libodphelper-linux-generic.pc.in > @@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@ > libdir=@libdir@ > includedir=@includedir@ > > -Name: libodphelper-linux > +Name: libodphelper-linux-generic > Description: Helper for the ODP packet processing engine > Version: @PKGCONFIG_VERSION@ > -Libs: -L${libdir} -lodphelper-linux > +Libs: -L${libdir} -lodphelper-linux-generic > Libs.private: > Cflags: -I${includedir} > diff --git a/test/Makefile.inc b/test/Makefile.inc > index 1ebc047..243a616 100644 > --- a/test/Makefile.inc > +++ b/test/Makefile.inc > @@ -4,7 +4,7 @@ LIB = $(top_builddir)/lib > #in the following line, the libs using the symbols should come before > #the libs containing them! The includer is given a chance to add things > #before libodp by setting PRE_LDADD before the inclusion. > -LDADD = $(PRE_LDADD) $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > +LDADD = $(PRE_LDADD) $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > > INCFLAGS = \ > -I$(top_builddir)/platform/@with_platform@/include \ > diff --git a/test/common_plat/validation/api/Makefile.inc b/test/common_plat/validation/api/Makefile.inc > index ffba620..a0afd26 100644 > --- a/test/common_plat/validation/api/Makefile.inc > +++ b/test/common_plat/validation/api/Makefile.inc > @@ -13,4 +13,4 @@ AM_LDFLAGS += -static > LIBCUNIT_COMMON = $(COMMON_DIR)/libcunit_common.la > LIBCPUMASK_COMMON = $(COMMON_DIR)/libcpumask_common.la > LIBTHRMASK_COMMON = $(COMMON_DIR)/libthrmask_common.la > -LIBODP = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > +LIBODP = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > diff --git a/test/linux-generic/Makefile.inc b/test/linux-generic/Makefile.inc > index 36745fe..2a49076 100644 > --- a/test/linux-generic/Makefile.inc > +++ b/test/linux-generic/Makefile.inc > @@ -6,7 +6,7 @@ AM_LDFLAGS += -static > > LIBCUNIT_COMMON = $(top_builddir)/test/common_plat/common/libcunit_common.la > LIB = $(top_builddir)/lib > -LIBODP = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > +LIBODP = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > > INCCUNIT_COMMON = -I$(top_srcdir)/test/common_plat/common > INCODP = \ > -- > 2.9.3 >
On 2016-12-23 14:15, Mike Holmes wrote: > Only the portable api is built by default, use --enable-helper-extn > to enable non portable APIs for a helper platform > > Signed-off-by: Mike Holmes <mike.holmes@linaro.org> > --- I am probably missing something, but, seen from the original file, I would have expected everything preceeding the following comment... /* * wrapper for odpthreads, either implemented as linux threads or processes. * (in process mode, if start_routine returns NULL, the process return FAILURE). */ ...to be in the linux part. (I already did the separation as I expected the linux only stuff to be deleted, but that was nacked as you know) Why isn't it as simple as I thought? Mike: You can HO me when you have time Christophe > configure.ac | 17 +- > example/Makefile.inc | 2 +- > helper/Makefile.am | 15 +- > .../helper/platform/linux-generic/threads_extn.h | 112 ++++++++ > helper/include/odp/helper/threads.h | 76 ----- > helper/m4/configure.m4 | 11 + > helper/odph_thread_internal.h | 27 ++ > helper/platform/linux-generic/thread.c | 256 +++++++++++++++++ > helper/test/Makefile.am | 17 +- > helper/test/linux-generic/Makefile.am | 5 + > helper/test/{ => linux-generic}/process.c | 2 +- > helper/test/{ => linux-generic}/thread.c | 2 +- > helper/threads.c | 314 ++++----------------- > ...inux.pc.in => libodphelper-linux-generic.pc.in} | 4 +- > test/Makefile.inc | 2 +- > test/common_plat/validation/api/Makefile.inc | 2 +- > test/linux-generic/Makefile.inc | 2 +- > 17 files changed, 515 insertions(+), 351 deletions(-) > create mode 100644 helper/include/odp/helper/platform/linux-generic/threads_extn.h > create mode 100644 helper/odph_thread_internal.h > create mode 100644 helper/platform/linux-generic/thread.c > create mode 100644 helper/test/linux-generic/Makefile.am > rename helper/test/{ => linux-generic}/process.c (97%) > rename helper/test/{ => linux-generic}/thread.c (97%) > rename pkgconfig/{libodphelper-linux.pc.in => libodphelper-linux-generic.pc.in} (72%) > > diff --git a/configure.ac b/configure.ac > index 4fec9d5..001cab9 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -138,6 +138,18 @@ AC_SUBST([with_platform]) > AC_SUBST([platform_with_platform], ["platform/${with_platform}"]) > > ########################################################################## > +# Determine which helper platform to build for > +########################################################################## > +AC_ARG_WITH([helper_platform], > + [AS_HELP_STRING([--with-helper_platform=platform], > + [select helper platform to be used, default linux-generic])], > + [], > + [with_helper_platform=${with_platform} > + ]) > + > +AC_SUBST([with_helper_platform]) > + > +########################################################################## > # Run platform specific checks and settings > ########################################################################## > IMPLEMENTATION_NAME="" > @@ -202,6 +214,7 @@ AM_CONDITIONAL([test_example], [test x$test_example = xyes ]) > AM_CONDITIONAL([HAVE_DOXYGEN], [test "x${DOXYGEN}" = "xdoxygen"]) > AM_CONDITIONAL([user_guide], [test "x${user_guides}" = "xyes" ]) > AM_CONDITIONAL([HAVE_MSCGEN], [test "x${MSCGEN}" = "xmscgen"]) > +AM_CONDITIONAL([helper_ext], [test x$helper_ext = xyes ]) > > ########################################################################## > # Setup doxygen documentation > @@ -293,7 +306,7 @@ AM_CXXFLAGS="-std=c++11" > > AC_CONFIG_FILES([Makefile > pkgconfig/libodp-linux.pc > - pkgconfig/libodphelper-linux.pc > + pkgconfig/libodphelper-linux-generic.pc > ]) > > AC_SEARCH_LIBS([timer_create],[rt posix4]) > @@ -320,6 +333,8 @@ AC_MSG_RESULT([ > implementation_name: ${IMPLEMENTATION_NAME} > ARCH_DIR ${ARCH_DIR} > with_platform: ${with_platform} > + with_helper_platform: ${with_helper_platform} > + helper_ext: ${helper_ext} > prefix: ${prefix} > sysconfdir: ${sysconfdir} > libdir: ${libdir} > diff --git a/example/Makefile.inc b/example/Makefile.inc > index 19d3994..ea596d5 100644 > --- a/example/Makefile.inc > +++ b/example/Makefile.inc > @@ -1,6 +1,6 @@ > include $(top_srcdir)/platform/@with_platform@/Makefile.inc > LIB = $(top_builddir)/lib > -LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper-linux.la > +LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper-@with_helper_platform@.la > AM_CFLAGS += \ > -I$(srcdir) \ > -I$(top_srcdir)/example \ > diff --git a/helper/Makefile.am b/helper/Makefile.am > index 71c6975..66d60dd 100644 > --- a/helper/Makefile.am > +++ b/helper/Makefile.am > @@ -1,7 +1,7 @@ > include $(top_srcdir)/platform/@with_platform@/Makefile.inc > > pkgconfigdir = $(libdir)/pkgconfig > -pkgconfig_DATA = $(top_builddir)/pkgconfig/libodphelper-linux.pc > +pkgconfig_DATA = $(top_builddir)/pkgconfig/libodphelper-@with_helper_platform@.pc > > LIB = $(top_builddir)/lib > AM_CFLAGS = -I$(srcdir)/include > @@ -25,18 +25,25 @@ helperinclude_HEADERS = \ > $(srcdir)/include/odp/helper/table.h\ > $(srcdir)/include/odp/helper/udp.h > > +if helper_ext > +helperinclude_HEADERS += \ > + $(srcdir)/include/odp/helper/platform/@with_helper_platform@/threads_extn.h > +endif > + > noinst_HEADERS = \ > $(srcdir)/odph_debug.h \ > $(srcdir)/odph_hashtable.h \ > $(srcdir)/odph_lineartable.h \ > - $(srcdir)/odph_list_internal.h > + $(srcdir)/odph_list_internal.h \ > + $(srcdir)/odph_thread_internal.h > > -__LIB__libodphelper_linux_la_SOURCES = \ > +__LIB__libodphelper_@with_helper_platform@_la_SOURCES = \ > eth.c \ > ip.c \ > chksum.c \ > threads.c \ > + platform/@with_helper_platform@/thread.c \ > hashtable.c \ > lineartable.c > > -lib_LTLIBRARIES = $(LIB)/libodphelper-linux.la > +lib_LTLIBRARIES = $(LIB)/libodphelper-@with_helper_platform@.la > diff --git a/helper/include/odp/helper/platform/linux-generic/threads_extn.h b/helper/include/odp/helper/platform/linux-generic/threads_extn.h > new file mode 100644 > index 0000000..1d4036d > --- /dev/null > +++ b/helper/include/odp/helper/platform/linux-generic/threads_extn.h > @@ -0,0 +1,112 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP Linux helper extension API > + * > + * This file is an optional helper to odp.h APIs. These functions are provided > + * to ease common setups in a Linux system. User is free to implement the same > + * setups in otherways (not via this API). > + */ > + > +#ifndef ODPH_LINUX_EXT_H_ > +#define ODPH_LINUX_EXT_H_ > + > +#include <odp/helper/threads.h> > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** @addtogroup odph_linux ODPH LINUX > + * @{ > + */ > + > +/** > + * Creates and launches pthreads > + * > + * Creates, pins and launches threads to separate CPU's based on the cpumask. > + * > + * @param[out] pthread_tbl Table of pthread state information records. Table > + * must have at least as many entries as there are > + * CPUs in the CPU mask. > + * @param mask CPU mask > + * @param thr_params Linux helper thread parameters > + * > + * @return Number of threads created > + */ > +int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params); > + > +/** > + * Waits pthreads to exit > + * > + * Returns when all threads have been exit. > + * > + * @param thread_tbl Thread table > + * @param num Number of threads to create > + * > + */ > +void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num); > + > +/** > + * Fork a process > + * > + * Forks and sets CPU affinity for the child process. Ignores 'start' and 'arg' > + * thread parameters. > + * > + * @param[out] proc Pointer to process state info (for output) > + * @param cpu Destination CPU for the child process > + * @param thr_params Linux helper thread parameters > + * > + * @return On success: 1 for the parent, 0 for the child > + * On failure: -1 for the parent, -2 for the child > + */ > +int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > + const odph_linux_thr_params_t *thr_params); > + > +/** > + * Fork a number of processes > + * > + * Forks and sets CPU affinity for child processes. Ignores 'start' and 'arg' > + * thread parameters. > + * > + * @param[out] proc_tbl Process state info table (for output) > + * @param mask CPU mask of processes to create > + * @param thr_params Linux helper thread parameters > + * > + * @return On success: 1 for the parent, 0 for the child > + * On failure: -1 for the parent, -2 for the child > + */ > +int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params); > + > +/** > + * Wait for a number of processes > + * > + * Waits for a number of child processes to terminate. Records process state > + * change status into the process state info structure. > + * > + * @param proc_tbl Process state info table (previously filled by fork) > + * @param num Number of processes to wait > + * > + * @return 0 on success, -1 on failure > + */ > +int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num); > + > +/** > + * @} > + */ > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/helper/include/odp/helper/threads.h b/helper/include/odp/helper/threads.h > index b8d975a..5682bab 100644 > --- a/helper/include/odp/helper/threads.h > +++ b/helper/include/odp/helper/threads.h > @@ -93,82 +93,6 @@ typedef struct { > } odph_odpthread_t; > > /** > - * Creates and launches pthreads > - * > - * Creates, pins and launches threads to separate CPU's based on the cpumask. > - * > - * @param[out] pthread_tbl Table of pthread state information records. Table > - * must have at least as many entries as there are > - * CPUs in the CPU mask. > - * @param mask CPU mask > - * @param thr_params Linux helper thread parameters > - * > - * @return Number of threads created > - */ > -int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params); > - > -/** > - * Waits pthreads to exit > - * > - * Returns when all threads have been exit. > - * > - * @param thread_tbl Thread table > - * @param num Number of threads to create > - * > - */ > -void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num); > - > -/** > - * Fork a process > - * > - * Forks and sets CPU affinity for the child process. Ignores 'start' and 'arg' > - * thread parameters. > - * > - * @param[out] proc Pointer to process state info (for output) > - * @param cpu Destination CPU for the child process > - * @param thr_params Linux helper thread parameters > - * > - * @return On success: 1 for the parent, 0 for the child > - * On failure: -1 for the parent, -2 for the child > - */ > -int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > - const odph_linux_thr_params_t *thr_params); > - > - > -/** > - * Fork a number of processes > - * > - * Forks and sets CPU affinity for child processes. Ignores 'start' and 'arg' > - * thread parameters. > - * > - * @param[out] proc_tbl Process state info table (for output) > - * @param mask CPU mask of processes to create > - * @param thr_params Linux helper thread parameters > - * > - * @return On success: 1 for the parent, 0 for the child > - * On failure: -1 for the parent, -2 for the child > - */ > -int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params); > - > - > -/** > - * Wait for a number of processes > - * > - * Waits for a number of child processes to terminate. Records process state > - * change status into the process state info structure. > - * > - * @param proc_tbl Process state info table (previously filled by fork) > - * @param num Number of processes to wait > - * > - * @return 0 on success, -1 on failure > - */ > -int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num); > - > -/** > * Creates and launches odpthreads (as linux threads or processes) > * > * Creates, pins and launches threads to separate CPU's based on the cpumask. > diff --git a/helper/m4/configure.m4 b/helper/m4/configure.m4 > index b8a21f7..8f1c929 100644 > --- a/helper/m4/configure.m4 > +++ b/helper/m4/configure.m4 > @@ -8,5 +8,16 @@ AC_ARG_ENABLE([test-helper], > test_helper=yes > fi]) > > +########################################################################## > +# Enable/disable helper-ext > +# platform specific non portable extensions > +########################################################################## > +helper_ext=no > +AC_ARG_ENABLE([helper-ext], > + [ --enable-helper-ext build helper platform extensions (not portable)], > + [if test "x$enableval" = "xyes"; then > + helper_ext=yes > + fi]) > + > AC_CONFIG_FILES([helper/Makefile > helper/test/Makefile]) > diff --git a/helper/odph_thread_internal.h b/helper/odph_thread_internal.h > new file mode 100644 > index 0000000..24d5e09 > --- /dev/null > +++ b/helper/odph_thread_internal.h > @@ -0,0 +1,27 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP Helper internal thread APIs > + */ > + > +#ifndef ODPH_THREAD_INTERNAL_H_ > +#define ODPH_THREAD_INTERNAL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +void *_odph_run_start_routine(void *arg); > +void *_odph_thread_run_start_routine(void *arg); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/helper/platform/linux-generic/thread.c b/helper/platform/linux-generic/thread.c > new file mode 100644 > index 0000000..b6424a7 > --- /dev/null > +++ b/helper/platform/linux-generic/thread.c > @@ -0,0 +1,256 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef _GNU_SOURCE > +#define _GNU_SOURCE > +#endif > +#include <sched.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <sys/prctl.h> > +#include <sys/syscall.h> > + > +#include <stdlib.h> > +#include <string.h> > +#include <stdio.h> > +#include <stdbool.h> > + > +#include <odp_api.h> > +#include <odp/helper/platform/linux-generic/threads_extn.h> > +#include <odph_thread_internal.h> > +#include "odph_debug.h" > + > +int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params) > +{ > + int i; > + int num; > + int cpu_count; > + int cpu; > + int ret; > + > + num = odp_cpumask_count(mask); > + > + memset(pthread_tbl, 0, num * sizeof(odph_linux_pthread_t)); > + > + cpu_count = odp_cpu_count(); > + > + if (num < 1 || num > cpu_count) { > + ODPH_ERR("Invalid number of threads:%d (%d cores available)\n", > + num, cpu_count); > + return 0; > + } > + > + cpu = odp_cpumask_first(mask); > + for (i = 0; i < num; i++) { > + cpu_set_t cpu_set; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + pthread_attr_init(&pthread_tbl[i].attr); > + > + pthread_tbl[i].cpu = cpu; > + > + pthread_attr_setaffinity_np(&pthread_tbl[i].attr, > + sizeof(cpu_set_t), &cpu_set); > + > + pthread_tbl[i].thr_params.start = thr_params->start; > + pthread_tbl[i].thr_params.arg = thr_params->arg; > + pthread_tbl[i].thr_params.thr_type = thr_params->thr_type; > + pthread_tbl[i].thr_params.instance = thr_params->instance; > + > + ret = pthread_create(&pthread_tbl[i].thread, > + &pthread_tbl[i].attr, > + _odph_run_start_routine, > + &pthread_tbl[i].thr_params); > + if (ret != 0) { > + ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > + break; > + } > + > + cpu = odp_cpumask_next(mask, cpu); > + } > + > + return i; > +} > + > +void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num) > +{ > + int i; > + int ret; > + > + for (i = 0; i < num; i++) { > + /* Wait thread to exit */ > + ret = pthread_join(thread_tbl[i].thread, NULL); > + if (ret != 0) { > + ODPH_ERR("Failed to join thread from cpu #%d\n", > + thread_tbl[i].cpu); > + } > + pthread_attr_destroy(&thread_tbl[i].attr); > + } > +} > + > +int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > + const odp_cpumask_t *mask, > + const odph_linux_thr_params_t *thr_params) > +{ > + pid_t pid; > + int num; > + int cpu_count; > + int cpu; > + int i; > + > + num = odp_cpumask_count(mask); > + > + memset(proc_tbl, 0, num * sizeof(odph_linux_process_t)); > + > + cpu_count = odp_cpu_count(); > + > + if (num < 1 || num > cpu_count) { > + ODPH_ERR("Bad num\n"); > + return -1; > + } > + > + cpu = odp_cpumask_first(mask); > + for (i = 0; i < num; i++) { > + cpu_set_t cpu_set; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + pid = fork(); > + > + if (pid < 0) { > + ODPH_ERR("fork() failed\n"); > + return -1; > + } > + > + /* Parent continues to fork */ > + if (pid > 0) { > + proc_tbl[i].pid = pid; > + proc_tbl[i].cpu = cpu; > + > + cpu = odp_cpumask_next(mask, cpu); > + continue; > + } > + > + /* Child process */ > + > + /* Request SIGTERM if parent dies */ > + prctl(PR_SET_PDEATHSIG, SIGTERM); > + /* Parent died already? */ > + if (getppid() == 1) > + kill(getpid(), SIGTERM); > + > + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > + ODPH_ERR("sched_setaffinity() failed\n"); > + return -2; > + } > + > + if (odp_init_local(thr_params->instance, > + thr_params->thr_type)) { > + ODPH_ERR("Local init failed\n"); > + return -2; > + } > + > + return 0; > + } > + > + return 1; > +} > + > +int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > + const odph_linux_thr_params_t *thr_params) > +{ > + odp_cpumask_t mask; > + > + odp_cpumask_zero(&mask); > + odp_cpumask_set(&mask, cpu); > + return odph_linux_process_fork_n(proc, &mask, thr_params); > +} > + > +int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num) > +{ > + pid_t pid; > + int i, j; > + int status = 0; > + > + for (i = 0; i < num; i++) { > + pid = wait(&status); > + > + if (pid < 0) { > + ODPH_ERR("wait() failed\n"); > + return -1; > + } > + > + for (j = 0; j < num; j++) { > + if (proc_tbl[j].pid == pid) { > + proc_tbl[j].status = status; > + break; > + } > + } > + > + if (j == num) { > + ODPH_ERR("Bad pid:%d\n", (int)pid); > + return -1; > + } > + > + /* Examine the child process' termination status */ > + if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) { > + ODPH_ERR("Child exit status:%d (pid:%d)\n", > + WEXITSTATUS(status), (int)pid); > + return -1; > + } > + if (WIFSIGNALED(status)) { > + int signo = WTERMSIG(status); > + > + ODPH_ERR("Child term signo:%d - %s (pid:%d)\n", > + signo, strsignal(signo), (int)pid); > + return -1; > + } > + } > + > + return 0; > +} > + > +/* > + * Create a single ODPthread as a linux thread > + */ > +static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, > + int cpu, > + const odph_odpthread_params_t *thr_params) > +{ > + int ret; > + cpu_set_t cpu_set; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + pthread_attr_init(&thread_tbl->thread.attr); > + > + thread_tbl->cpu = cpu; > + > + pthread_attr_setaffinity_np(&thread_tbl->thread.attr, > + sizeof(cpu_set_t), &cpu_set); > + > + thread_tbl->start_args.thr_params = *thr_params; /* copy */ > + thread_tbl->start_args.linuxtype = ODPTHREAD_PTHREAD; > + > + ret = pthread_create(&thread_tbl->thread.thread_id, > + &thread_tbl->thread.attr, > + _odph_thread_run_start_routine, > + &thread_tbl->start_args); > + if (ret != 0) { > + ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > + thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; > + return ret; > + } > + > + return 0; > +} > diff --git a/helper/test/Makefile.am b/helper/test/Makefile.am > index 545db73..47dcb86 100644 > --- a/helper/test/Makefile.am > +++ b/helper/test/Makefile.am > @@ -6,11 +6,18 @@ AM_LDFLAGS += -static > TESTS_ENVIRONMENT += TEST_DIR=${builddir} > > EXECUTABLES = chksum$(EXEEXT) \ > - thread$(EXEEXT) \ > parse$(EXEEXT)\ > - process$(EXEEXT)\ > table$(EXEEXT) > > +#These are platform specific extensions that are not portable > +#They are a convenience to app writers who have chosen to > +#restrict their application to Linux. > + > +if helper_ext > +EXECUTABLES += @with_helper_platform@/thread$(EXEEXT) \ > + @with_helper_platform@/process$(EXEEXT) > +endif > + > COMPILE_ONLY = odpthreads > > TESTSCRIPTS = odpthreads_as_processes \ > @@ -28,10 +35,6 @@ EXTRA_DIST = odpthreads_as_processes odpthreads_as_pthreads > > dist_chksum_SOURCES = chksum.c > dist_odpthreads_SOURCES = odpthreads.c > -odpthreads_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > -dist_thread_SOURCES = thread.c > -thread_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > -dist_process_SOURCES = process.c > +odpthreads_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > dist_parse_SOURCES = parse.c > -process_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > dist_table_SOURCES = table.c > diff --git a/helper/test/linux-generic/Makefile.am b/helper/test/linux-generic/Makefile.am > new file mode 100644 > index 0000000..28d54a8 > --- /dev/null > +++ b/helper/test/linux-generic/Makefile.am > @@ -0,0 +1,5 @@ > + > +thread_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > +dist_thread_SOURCES = thread.c > +dist_process_SOURCES = process.c > +process_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > diff --git a/helper/test/process.c b/helper/test/linux-generic/process.c > similarity index 97% > rename from helper/test/process.c > rename to helper/test/linux-generic/process.c > index f3c6d50..f641128 100644 > --- a/helper/test/process.c > +++ b/helper/test/linux-generic/process.c > @@ -6,7 +6,7 @@ > > #include <test_debug.h> > #include <odp_api.h> > -#include <odp/helper/threads.h> > +#include <odp/helper/platform/linux-generic/threads_extn.h> > > #define NUMBER_WORKERS 16 /* 0 = max */ > > diff --git a/helper/test/thread.c b/helper/test/linux-generic/thread.c > similarity index 97% > rename from helper/test/thread.c > rename to helper/test/linux-generic/thread.c > index da94b49..f1ca1b7 100644 > --- a/helper/test/thread.c > +++ b/helper/test/linux-generic/thread.c > @@ -6,7 +6,7 @@ > > #include <test_debug.h> > #include <odp_api.h> > -#include <odp/helper/threads.h> > +#include <odp/helper/platform/linux-generic/threads_extn.h> > > #define NUMBER_WORKERS 16 > static void *worker_fn(void *arg TEST_UNUSED) > diff --git a/helper/threads.c b/helper/threads.c > index d5215c2..edfbe0e 100644 > --- a/helper/threads.c > +++ b/helper/threads.c > @@ -9,25 +9,24 @@ > #endif > #include <sched.h> > #include <unistd.h> > -#include <sys/types.h> > #include <sys/wait.h> > #include <sys/prctl.h> > #include <sys/syscall.h> > > -#include <stdlib.h> > -#include <string.h> > -#include <stdio.h> > -#include <stdbool.h> > - > #include <odp_api.h> > #include <odp/helper/threads.h> > #include "odph_debug.h" > > +static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, > + int cpu, > + const odph_odpthread_params_t *thr_params > + ); > + > static struct { > int proc; /* true when process mode is required, false otherwise */ > } helper_options; > > -static void *odp_run_start_routine(void *arg) > +void *_odph_run_start_routine(void *arg) > { > odph_linux_thr_params_t *thr_params = arg; > > @@ -48,206 +47,11 @@ static void *odp_run_start_routine(void *arg) > return ret_ptr; > } > > -int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params) > -{ > - int i; > - int num; > - int cpu_count; > - int cpu; > - int ret; > - > - num = odp_cpumask_count(mask); > - > - memset(pthread_tbl, 0, num * sizeof(odph_linux_pthread_t)); > - > - cpu_count = odp_cpu_count(); > - > - if (num < 1 || num > cpu_count) { > - ODPH_ERR("Invalid number of threads:%d (%d cores available)\n", > - num, cpu_count); > - return 0; > - } > - > - cpu = odp_cpumask_first(mask); > - for (i = 0; i < num; i++) { > - cpu_set_t cpu_set; > - > - CPU_ZERO(&cpu_set); > - CPU_SET(cpu, &cpu_set); > - > - pthread_attr_init(&pthread_tbl[i].attr); > - > - pthread_tbl[i].cpu = cpu; > - > - pthread_attr_setaffinity_np(&pthread_tbl[i].attr, > - sizeof(cpu_set_t), &cpu_set); > - > - pthread_tbl[i].thr_params.start = thr_params->start; > - pthread_tbl[i].thr_params.arg = thr_params->arg; > - pthread_tbl[i].thr_params.thr_type = thr_params->thr_type; > - pthread_tbl[i].thr_params.instance = thr_params->instance; > - > - ret = pthread_create(&pthread_tbl[i].thread, > - &pthread_tbl[i].attr, > - odp_run_start_routine, > - &pthread_tbl[i].thr_params); > - if (ret != 0) { > - ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > - break; > - } > - > - cpu = odp_cpumask_next(mask, cpu); > - } > - > - return i; > -} > - > -void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num) > -{ > - int i; > - int ret; > - > - for (i = 0; i < num; i++) { > - /* Wait thread to exit */ > - ret = pthread_join(thread_tbl[i].thread, NULL); > - if (ret != 0) { > - ODPH_ERR("Failed to join thread from cpu #%d\n", > - thread_tbl[i].cpu); > - } > - pthread_attr_destroy(&thread_tbl[i].attr); > - } > -} > - > -int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, > - const odp_cpumask_t *mask, > - const odph_linux_thr_params_t *thr_params) > -{ > - pid_t pid; > - int num; > - int cpu_count; > - int cpu; > - int i; > - > - num = odp_cpumask_count(mask); > - > - memset(proc_tbl, 0, num * sizeof(odph_linux_process_t)); > - > - cpu_count = odp_cpu_count(); > - > - if (num < 1 || num > cpu_count) { > - ODPH_ERR("Bad num\n"); > - return -1; > - } > - > - cpu = odp_cpumask_first(mask); > - for (i = 0; i < num; i++) { > - cpu_set_t cpu_set; > - > - CPU_ZERO(&cpu_set); > - CPU_SET(cpu, &cpu_set); > - > - pid = fork(); > - > - if (pid < 0) { > - ODPH_ERR("fork() failed\n"); > - return -1; > - } > - > - /* Parent continues to fork */ > - if (pid > 0) { > - proc_tbl[i].pid = pid; > - proc_tbl[i].cpu = cpu; > - > - cpu = odp_cpumask_next(mask, cpu); > - continue; > - } > - > - /* Child process */ > - > - /* Request SIGTERM if parent dies */ > - prctl(PR_SET_PDEATHSIG, SIGTERM); > - /* Parent died already? */ > - if (getppid() == 1) > - kill(getpid(), SIGTERM); > - > - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > - ODPH_ERR("sched_setaffinity() failed\n"); > - return -2; > - } > - > - if (odp_init_local(thr_params->instance, > - thr_params->thr_type)) { > - ODPH_ERR("Local init failed\n"); > - return -2; > - } > - > - return 0; > - } > - > - return 1; > -} > - > -int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, > - const odph_linux_thr_params_t *thr_params) > -{ > - odp_cpumask_t mask; > - > - odp_cpumask_zero(&mask); > - odp_cpumask_set(&mask, cpu); > - return odph_linux_process_fork_n(proc, &mask, thr_params); > -} > - > -int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num) > -{ > - pid_t pid; > - int i, j; > - int status = 0; > - > - for (i = 0; i < num; i++) { > - pid = wait(&status); > - > - if (pid < 0) { > - ODPH_ERR("wait() failed\n"); > - return -1; > - } > - > - for (j = 0; j < num; j++) { > - if (proc_tbl[j].pid == pid) { > - proc_tbl[j].status = status; > - break; > - } > - } > - > - if (j == num) { > - ODPH_ERR("Bad pid:%d\n", (int)pid); > - return -1; > - } > - > - /* Examine the child process' termination status */ > - if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) { > - ODPH_ERR("Child exit status:%d (pid:%d)\n", > - WEXITSTATUS(status), (int)pid); > - return -1; > - } > - if (WIFSIGNALED(status)) { > - int signo = WTERMSIG(status); > - > - ODPH_ERR("Child term signo:%d - %s (pid:%d)\n", > - signo, strsignal(signo), (int)pid); > - return -1; > - } > - } > - > - return 0; > -} > - > /* > * wrapper for odpthreads, either implemented as linux threads or processes. > * (in process mode, if start_routine returns NULL, the process return FAILURE). > */ > -static void *odpthread_run_start_routine(void *arg) > +void *_odph_thread_run_start_routine(void *arg) > { > int status; > int ret; > @@ -289,54 +93,6 @@ static void *odpthread_run_start_routine(void *arg) > } > > /* > - * Create a single ODPthread as a linux process > - */ > -static int odph_linux_process_create(odph_odpthread_t *thread_tbl, > - int cpu, > - const odph_odpthread_params_t *thr_params) > -{ > - cpu_set_t cpu_set; > - pid_t pid; > - > - CPU_ZERO(&cpu_set); > - CPU_SET(cpu, &cpu_set); > - > - thread_tbl->start_args.thr_params = *thr_params; /* copy */ > - thread_tbl->start_args.linuxtype = ODPTHREAD_PROCESS; > - thread_tbl->cpu = cpu; > - > - pid = fork(); > - if (pid < 0) { > - ODPH_ERR("fork() failed\n"); > - thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; > - return -1; > - } > - > - /* Parent continues to fork */ > - if (pid > 0) { > - thread_tbl->proc.pid = pid; > - return 0; > - } > - > - /* Child process */ > - > - /* Request SIGTERM if parent dies */ > - prctl(PR_SET_PDEATHSIG, SIGTERM); > - /* Parent died already? */ > - if (getppid() == 1) > - kill(getpid(), SIGTERM); > - > - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > - ODPH_ERR("sched_setaffinity() failed\n"); > - return -2; > - } > - > - odpthread_run_start_routine(&thread_tbl->start_args); > - > - return 0; /* never reached */ > -} > - > -/* > * Create a single ODPthread as a linux thread > */ > static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, > @@ -361,7 +117,7 @@ static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, > > ret = pthread_create(&thread_tbl->thread.thread_id, > &thread_tbl->thread.attr, > - odpthread_run_start_routine, > + _odph_thread_run_start_routine, > &thread_tbl->start_args); > if (ret != 0) { > ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); > @@ -405,9 +161,9 @@ int odph_odpthreads_create(odph_odpthread_t *thread_tbl, > thr_params)) > break; > } else { > - if (odph_linux_process_create(&thread_tbl[i], > - cpu, > - thr_params)) > + if (_odph_linux_process_create(&thread_tbl[i], > + cpu, > + thr_params)) > break; > } > > @@ -677,3 +433,51 @@ int odph_parse_options(int argc, char *argv[], > > return res; > } > + > +/* > + * Create a single ODPthread as a linux process > + */ > +static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, > + int cpu, > + const odph_odpthread_params_t *thr_params) > +{ > + cpu_set_t cpu_set; > + pid_t pid; > + > + CPU_ZERO(&cpu_set); > + CPU_SET(cpu, &cpu_set); > + > + thread_tbl->start_args.thr_params = *thr_params; /* copy */ > + thread_tbl->start_args.linuxtype = ODPTHREAD_PROCESS; > + thread_tbl->cpu = cpu; > + > + pid = fork(); > + if (pid < 0) { > + ODPH_ERR("fork() failed\n"); > + thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; > + return -1; > + } > + > + /* Parent continues to fork */ > + if (pid > 0) { > + thread_tbl->proc.pid = pid; > + return 0; > + } > + > + /* Child process */ > + > + /* Request SIGTERM if parent dies */ > + prctl(PR_SET_PDEATHSIG, SIGTERM); > + /* Parent died already? */ > + if (getppid() == 1) > + kill(getpid(), SIGTERM); > + > + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { > + ODPH_ERR("sched_setaffinity() failed\n"); > + return -2; > + } > + > + _odph_thread_run_start_routine(&thread_tbl->start_args); > + > + return 0; /* never reached */ > +} > diff --git a/pkgconfig/libodphelper-linux.pc.in b/pkgconfig/libodphelper-linux-generic.pc.in > similarity index 72% > rename from pkgconfig/libodphelper-linux.pc.in > rename to pkgconfig/libodphelper-linux-generic.pc.in > index 3987f4c..cab7be2 100644 > --- a/pkgconfig/libodphelper-linux.pc.in > +++ b/pkgconfig/libodphelper-linux-generic.pc.in > @@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@ > libdir=@libdir@ > includedir=@includedir@ > > -Name: libodphelper-linux > +Name: libodphelper-linux-generic > Description: Helper for the ODP packet processing engine > Version: @PKGCONFIG_VERSION@ > -Libs: -L${libdir} -lodphelper-linux > +Libs: -L${libdir} -lodphelper-linux-generic > Libs.private: > Cflags: -I${includedir} > diff --git a/test/Makefile.inc b/test/Makefile.inc > index 1ebc047..243a616 100644 > --- a/test/Makefile.inc > +++ b/test/Makefile.inc > @@ -4,7 +4,7 @@ LIB = $(top_builddir)/lib > #in the following line, the libs using the symbols should come before > #the libs containing them! The includer is given a chance to add things > #before libodp by setting PRE_LDADD before the inclusion. > -LDADD = $(PRE_LDADD) $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > +LDADD = $(PRE_LDADD) $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > > INCFLAGS = \ > -I$(top_builddir)/platform/@with_platform@/include \ > diff --git a/test/common_plat/validation/api/Makefile.inc b/test/common_plat/validation/api/Makefile.inc > index ffba620..a0afd26 100644 > --- a/test/common_plat/validation/api/Makefile.inc > +++ b/test/common_plat/validation/api/Makefile.inc > @@ -13,4 +13,4 @@ AM_LDFLAGS += -static > LIBCUNIT_COMMON = $(COMMON_DIR)/libcunit_common.la > LIBCPUMASK_COMMON = $(COMMON_DIR)/libcpumask_common.la > LIBTHRMASK_COMMON = $(COMMON_DIR)/libthrmask_common.la > -LIBODP = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > +LIBODP = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > diff --git a/test/linux-generic/Makefile.inc b/test/linux-generic/Makefile.inc > index 36745fe..2a49076 100644 > --- a/test/linux-generic/Makefile.inc > +++ b/test/linux-generic/Makefile.inc > @@ -6,7 +6,7 @@ AM_LDFLAGS += -static > > LIBCUNIT_COMMON = $(top_builddir)/test/common_plat/common/libcunit_common.la > LIB = $(top_builddir)/lib > -LIBODP = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la > +LIBODP = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la > > INCCUNIT_COMMON = -I$(top_srcdir)/test/common_plat/common > INCODP = \ > -- > 2.9.3 >
diff --git a/configure.ac b/configure.ac index 4fec9d5..001cab9 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,18 @@ AC_SUBST([with_platform]) AC_SUBST([platform_with_platform], ["platform/${with_platform}"]) ########################################################################## +# Determine which helper platform to build for +########################################################################## +AC_ARG_WITH([helper_platform], + [AS_HELP_STRING([--with-helper_platform=platform], + [select helper platform to be used, default linux-generic])], + [], + [with_helper_platform=${with_platform} + ]) + +AC_SUBST([with_helper_platform]) + +########################################################################## # Run platform specific checks and settings ########################################################################## IMPLEMENTATION_NAME="" @@ -202,6 +214,7 @@ AM_CONDITIONAL([test_example], [test x$test_example = xyes ]) AM_CONDITIONAL([HAVE_DOXYGEN], [test "x${DOXYGEN}" = "xdoxygen"]) AM_CONDITIONAL([user_guide], [test "x${user_guides}" = "xyes" ]) AM_CONDITIONAL([HAVE_MSCGEN], [test "x${MSCGEN}" = "xmscgen"]) +AM_CONDITIONAL([helper_ext], [test x$helper_ext = xyes ]) ########################################################################## # Setup doxygen documentation @@ -293,7 +306,7 @@ AM_CXXFLAGS="-std=c++11" AC_CONFIG_FILES([Makefile pkgconfig/libodp-linux.pc - pkgconfig/libodphelper-linux.pc + pkgconfig/libodphelper-linux-generic.pc ]) AC_SEARCH_LIBS([timer_create],[rt posix4]) @@ -320,6 +333,8 @@ AC_MSG_RESULT([ implementation_name: ${IMPLEMENTATION_NAME} ARCH_DIR ${ARCH_DIR} with_platform: ${with_platform} + with_helper_platform: ${with_helper_platform} + helper_ext: ${helper_ext} prefix: ${prefix} sysconfdir: ${sysconfdir} libdir: ${libdir} diff --git a/example/Makefile.inc b/example/Makefile.inc index 19d3994..ea596d5 100644 --- a/example/Makefile.inc +++ b/example/Makefile.inc @@ -1,6 +1,6 @@ include $(top_srcdir)/platform/@with_platform@/Makefile.inc LIB = $(top_builddir)/lib -LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper-linux.la +LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper-@with_helper_platform@.la AM_CFLAGS += \ -I$(srcdir) \ -I$(top_srcdir)/example \ diff --git a/helper/Makefile.am b/helper/Makefile.am index 71c6975..66d60dd 100644 --- a/helper/Makefile.am +++ b/helper/Makefile.am @@ -1,7 +1,7 @@ include $(top_srcdir)/platform/@with_platform@/Makefile.inc pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = $(top_builddir)/pkgconfig/libodphelper-linux.pc +pkgconfig_DATA = $(top_builddir)/pkgconfig/libodphelper-@with_helper_platform@.pc LIB = $(top_builddir)/lib AM_CFLAGS = -I$(srcdir)/include @@ -25,18 +25,25 @@ helperinclude_HEADERS = \ $(srcdir)/include/odp/helper/table.h\ $(srcdir)/include/odp/helper/udp.h +if helper_ext +helperinclude_HEADERS += \ + $(srcdir)/include/odp/helper/platform/@with_helper_platform@/threads_extn.h +endif + noinst_HEADERS = \ $(srcdir)/odph_debug.h \ $(srcdir)/odph_hashtable.h \ $(srcdir)/odph_lineartable.h \ - $(srcdir)/odph_list_internal.h + $(srcdir)/odph_list_internal.h \ + $(srcdir)/odph_thread_internal.h -__LIB__libodphelper_linux_la_SOURCES = \ +__LIB__libodphelper_@with_helper_platform@_la_SOURCES = \ eth.c \ ip.c \ chksum.c \ threads.c \ + platform/@with_helper_platform@/thread.c \ hashtable.c \ lineartable.c -lib_LTLIBRARIES = $(LIB)/libodphelper-linux.la +lib_LTLIBRARIES = $(LIB)/libodphelper-@with_helper_platform@.la diff --git a/helper/include/odp/helper/platform/linux-generic/threads_extn.h b/helper/include/odp/helper/platform/linux-generic/threads_extn.h new file mode 100644 index 0000000..1d4036d --- /dev/null +++ b/helper/include/odp/helper/platform/linux-generic/threads_extn.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP Linux helper extension API + * + * This file is an optional helper to odp.h APIs. These functions are provided + * to ease common setups in a Linux system. User is free to implement the same + * setups in otherways (not via this API). + */ + +#ifndef ODPH_LINUX_EXT_H_ +#define ODPH_LINUX_EXT_H_ + +#include <odp/helper/threads.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup odph_linux ODPH LINUX + * @{ + */ + +/** + * Creates and launches pthreads + * + * Creates, pins and launches threads to separate CPU's based on the cpumask. + * + * @param[out] pthread_tbl Table of pthread state information records. Table + * must have at least as many entries as there are + * CPUs in the CPU mask. + * @param mask CPU mask + * @param thr_params Linux helper thread parameters + * + * @return Number of threads created + */ +int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, + const odp_cpumask_t *mask, + const odph_linux_thr_params_t *thr_params); + +/** + * Waits pthreads to exit + * + * Returns when all threads have been exit. + * + * @param thread_tbl Thread table + * @param num Number of threads to create + * + */ +void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num); + +/** + * Fork a process + * + * Forks and sets CPU affinity for the child process. Ignores 'start' and 'arg' + * thread parameters. + * + * @param[out] proc Pointer to process state info (for output) + * @param cpu Destination CPU for the child process + * @param thr_params Linux helper thread parameters + * + * @return On success: 1 for the parent, 0 for the child + * On failure: -1 for the parent, -2 for the child + */ +int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, + const odph_linux_thr_params_t *thr_params); + +/** + * Fork a number of processes + * + * Forks and sets CPU affinity for child processes. Ignores 'start' and 'arg' + * thread parameters. + * + * @param[out] proc_tbl Process state info table (for output) + * @param mask CPU mask of processes to create + * @param thr_params Linux helper thread parameters + * + * @return On success: 1 for the parent, 0 for the child + * On failure: -1 for the parent, -2 for the child + */ +int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, + const odp_cpumask_t *mask, + const odph_linux_thr_params_t *thr_params); + +/** + * Wait for a number of processes + * + * Waits for a number of child processes to terminate. Records process state + * change status into the process state info structure. + * + * @param proc_tbl Process state info table (previously filled by fork) + * @param num Number of processes to wait + * + * @return 0 on success, -1 on failure + */ +int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/helper/include/odp/helper/threads.h b/helper/include/odp/helper/threads.h index b8d975a..5682bab 100644 --- a/helper/include/odp/helper/threads.h +++ b/helper/include/odp/helper/threads.h @@ -93,82 +93,6 @@ typedef struct { } odph_odpthread_t; /** - * Creates and launches pthreads - * - * Creates, pins and launches threads to separate CPU's based on the cpumask. - * - * @param[out] pthread_tbl Table of pthread state information records. Table - * must have at least as many entries as there are - * CPUs in the CPU mask. - * @param mask CPU mask - * @param thr_params Linux helper thread parameters - * - * @return Number of threads created - */ -int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, - const odp_cpumask_t *mask, - const odph_linux_thr_params_t *thr_params); - -/** - * Waits pthreads to exit - * - * Returns when all threads have been exit. - * - * @param thread_tbl Thread table - * @param num Number of threads to create - * - */ -void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num); - -/** - * Fork a process - * - * Forks and sets CPU affinity for the child process. Ignores 'start' and 'arg' - * thread parameters. - * - * @param[out] proc Pointer to process state info (for output) - * @param cpu Destination CPU for the child process - * @param thr_params Linux helper thread parameters - * - * @return On success: 1 for the parent, 0 for the child - * On failure: -1 for the parent, -2 for the child - */ -int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, - const odph_linux_thr_params_t *thr_params); - - -/** - * Fork a number of processes - * - * Forks and sets CPU affinity for child processes. Ignores 'start' and 'arg' - * thread parameters. - * - * @param[out] proc_tbl Process state info table (for output) - * @param mask CPU mask of processes to create - * @param thr_params Linux helper thread parameters - * - * @return On success: 1 for the parent, 0 for the child - * On failure: -1 for the parent, -2 for the child - */ -int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, - const odp_cpumask_t *mask, - const odph_linux_thr_params_t *thr_params); - - -/** - * Wait for a number of processes - * - * Waits for a number of child processes to terminate. Records process state - * change status into the process state info structure. - * - * @param proc_tbl Process state info table (previously filled by fork) - * @param num Number of processes to wait - * - * @return 0 on success, -1 on failure - */ -int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num); - -/** * Creates and launches odpthreads (as linux threads or processes) * * Creates, pins and launches threads to separate CPU's based on the cpumask. diff --git a/helper/m4/configure.m4 b/helper/m4/configure.m4 index b8a21f7..8f1c929 100644 --- a/helper/m4/configure.m4 +++ b/helper/m4/configure.m4 @@ -8,5 +8,16 @@ AC_ARG_ENABLE([test-helper], test_helper=yes fi]) +########################################################################## +# Enable/disable helper-ext +# platform specific non portable extensions +########################################################################## +helper_ext=no +AC_ARG_ENABLE([helper-ext], + [ --enable-helper-ext build helper platform extensions (not portable)], + [if test "x$enableval" = "xyes"; then + helper_ext=yes + fi]) + AC_CONFIG_FILES([helper/Makefile helper/test/Makefile]) diff --git a/helper/odph_thread_internal.h b/helper/odph_thread_internal.h new file mode 100644 index 0000000..24d5e09 --- /dev/null +++ b/helper/odph_thread_internal.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP Helper internal thread APIs + */ + +#ifndef ODPH_THREAD_INTERNAL_H_ +#define ODPH_THREAD_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void *_odph_run_start_routine(void *arg); +void *_odph_thread_run_start_routine(void *arg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/helper/platform/linux-generic/thread.c b/helper/platform/linux-generic/thread.c new file mode 100644 index 0000000..b6424a7 --- /dev/null +++ b/helper/platform/linux-generic/thread.c @@ -0,0 +1,256 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <sched.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/prctl.h> +#include <sys/syscall.h> + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdbool.h> + +#include <odp_api.h> +#include <odp/helper/platform/linux-generic/threads_extn.h> +#include <odph_thread_internal.h> +#include "odph_debug.h" + +int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, + const odp_cpumask_t *mask, + const odph_linux_thr_params_t *thr_params) +{ + int i; + int num; + int cpu_count; + int cpu; + int ret; + + num = odp_cpumask_count(mask); + + memset(pthread_tbl, 0, num * sizeof(odph_linux_pthread_t)); + + cpu_count = odp_cpu_count(); + + if (num < 1 || num > cpu_count) { + ODPH_ERR("Invalid number of threads:%d (%d cores available)\n", + num, cpu_count); + return 0; + } + + cpu = odp_cpumask_first(mask); + for (i = 0; i < num; i++) { + cpu_set_t cpu_set; + + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + + pthread_attr_init(&pthread_tbl[i].attr); + + pthread_tbl[i].cpu = cpu; + + pthread_attr_setaffinity_np(&pthread_tbl[i].attr, + sizeof(cpu_set_t), &cpu_set); + + pthread_tbl[i].thr_params.start = thr_params->start; + pthread_tbl[i].thr_params.arg = thr_params->arg; + pthread_tbl[i].thr_params.thr_type = thr_params->thr_type; + pthread_tbl[i].thr_params.instance = thr_params->instance; + + ret = pthread_create(&pthread_tbl[i].thread, + &pthread_tbl[i].attr, + _odph_run_start_routine, + &pthread_tbl[i].thr_params); + if (ret != 0) { + ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); + break; + } + + cpu = odp_cpumask_next(mask, cpu); + } + + return i; +} + +void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num) +{ + int i; + int ret; + + for (i = 0; i < num; i++) { + /* Wait thread to exit */ + ret = pthread_join(thread_tbl[i].thread, NULL); + if (ret != 0) { + ODPH_ERR("Failed to join thread from cpu #%d\n", + thread_tbl[i].cpu); + } + pthread_attr_destroy(&thread_tbl[i].attr); + } +} + +int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, + const odp_cpumask_t *mask, + const odph_linux_thr_params_t *thr_params) +{ + pid_t pid; + int num; + int cpu_count; + int cpu; + int i; + + num = odp_cpumask_count(mask); + + memset(proc_tbl, 0, num * sizeof(odph_linux_process_t)); + + cpu_count = odp_cpu_count(); + + if (num < 1 || num > cpu_count) { + ODPH_ERR("Bad num\n"); + return -1; + } + + cpu = odp_cpumask_first(mask); + for (i = 0; i < num; i++) { + cpu_set_t cpu_set; + + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + + pid = fork(); + + if (pid < 0) { + ODPH_ERR("fork() failed\n"); + return -1; + } + + /* Parent continues to fork */ + if (pid > 0) { + proc_tbl[i].pid = pid; + proc_tbl[i].cpu = cpu; + + cpu = odp_cpumask_next(mask, cpu); + continue; + } + + /* Child process */ + + /* Request SIGTERM if parent dies */ + prctl(PR_SET_PDEATHSIG, SIGTERM); + /* Parent died already? */ + if (getppid() == 1) + kill(getpid(), SIGTERM); + + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { + ODPH_ERR("sched_setaffinity() failed\n"); + return -2; + } + + if (odp_init_local(thr_params->instance, + thr_params->thr_type)) { + ODPH_ERR("Local init failed\n"); + return -2; + } + + return 0; + } + + return 1; +} + +int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, + const odph_linux_thr_params_t *thr_params) +{ + odp_cpumask_t mask; + + odp_cpumask_zero(&mask); + odp_cpumask_set(&mask, cpu); + return odph_linux_process_fork_n(proc, &mask, thr_params); +} + +int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num) +{ + pid_t pid; + int i, j; + int status = 0; + + for (i = 0; i < num; i++) { + pid = wait(&status); + + if (pid < 0) { + ODPH_ERR("wait() failed\n"); + return -1; + } + + for (j = 0; j < num; j++) { + if (proc_tbl[j].pid == pid) { + proc_tbl[j].status = status; + break; + } + } + + if (j == num) { + ODPH_ERR("Bad pid:%d\n", (int)pid); + return -1; + } + + /* Examine the child process' termination status */ + if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) { + ODPH_ERR("Child exit status:%d (pid:%d)\n", + WEXITSTATUS(status), (int)pid); + return -1; + } + if (WIFSIGNALED(status)) { + int signo = WTERMSIG(status); + + ODPH_ERR("Child term signo:%d - %s (pid:%d)\n", + signo, strsignal(signo), (int)pid); + return -1; + } + } + + return 0; +} + +/* + * Create a single ODPthread as a linux thread + */ +static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, + int cpu, + const odph_odpthread_params_t *thr_params) +{ + int ret; + cpu_set_t cpu_set; + + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + + pthread_attr_init(&thread_tbl->thread.attr); + + thread_tbl->cpu = cpu; + + pthread_attr_setaffinity_np(&thread_tbl->thread.attr, + sizeof(cpu_set_t), &cpu_set); + + thread_tbl->start_args.thr_params = *thr_params; /* copy */ + thread_tbl->start_args.linuxtype = ODPTHREAD_PTHREAD; + + ret = pthread_create(&thread_tbl->thread.thread_id, + &thread_tbl->thread.attr, + _odph_thread_run_start_routine, + &thread_tbl->start_args); + if (ret != 0) { + ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); + thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; + return ret; + } + + return 0; +} diff --git a/helper/test/Makefile.am b/helper/test/Makefile.am index 545db73..47dcb86 100644 --- a/helper/test/Makefile.am +++ b/helper/test/Makefile.am @@ -6,11 +6,18 @@ AM_LDFLAGS += -static TESTS_ENVIRONMENT += TEST_DIR=${builddir} EXECUTABLES = chksum$(EXEEXT) \ - thread$(EXEEXT) \ parse$(EXEEXT)\ - process$(EXEEXT)\ table$(EXEEXT) +#These are platform specific extensions that are not portable +#They are a convenience to app writers who have chosen to +#restrict their application to Linux. + +if helper_ext +EXECUTABLES += @with_helper_platform@/thread$(EXEEXT) \ + @with_helper_platform@/process$(EXEEXT) +endif + COMPILE_ONLY = odpthreads TESTSCRIPTS = odpthreads_as_processes \ @@ -28,10 +35,6 @@ EXTRA_DIST = odpthreads_as_processes odpthreads_as_pthreads dist_chksum_SOURCES = chksum.c dist_odpthreads_SOURCES = odpthreads.c -odpthreads_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la -dist_thread_SOURCES = thread.c -thread_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la -dist_process_SOURCES = process.c +odpthreads_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la dist_parse_SOURCES = parse.c -process_LDADD = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la dist_table_SOURCES = table.c diff --git a/helper/test/linux-generic/Makefile.am b/helper/test/linux-generic/Makefile.am new file mode 100644 index 0000000..28d54a8 --- /dev/null +++ b/helper/test/linux-generic/Makefile.am @@ -0,0 +1,5 @@ + +thread_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la +dist_thread_SOURCES = thread.c +dist_process_SOURCES = process.c +process_LDADD = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la diff --git a/helper/test/process.c b/helper/test/linux-generic/process.c similarity index 97% rename from helper/test/process.c rename to helper/test/linux-generic/process.c index f3c6d50..f641128 100644 --- a/helper/test/process.c +++ b/helper/test/linux-generic/process.c @@ -6,7 +6,7 @@ #include <test_debug.h> #include <odp_api.h> -#include <odp/helper/threads.h> +#include <odp/helper/platform/linux-generic/threads_extn.h> #define NUMBER_WORKERS 16 /* 0 = max */ diff --git a/helper/test/thread.c b/helper/test/linux-generic/thread.c similarity index 97% rename from helper/test/thread.c rename to helper/test/linux-generic/thread.c index da94b49..f1ca1b7 100644 --- a/helper/test/thread.c +++ b/helper/test/linux-generic/thread.c @@ -6,7 +6,7 @@ #include <test_debug.h> #include <odp_api.h> -#include <odp/helper/threads.h> +#include <odp/helper/platform/linux-generic/threads_extn.h> #define NUMBER_WORKERS 16 static void *worker_fn(void *arg TEST_UNUSED) diff --git a/helper/threads.c b/helper/threads.c index d5215c2..edfbe0e 100644 --- a/helper/threads.c +++ b/helper/threads.c @@ -9,25 +9,24 @@ #endif #include <sched.h> #include <unistd.h> -#include <sys/types.h> #include <sys/wait.h> #include <sys/prctl.h> #include <sys/syscall.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdbool.h> - #include <odp_api.h> #include <odp/helper/threads.h> #include "odph_debug.h" +static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, + int cpu, + const odph_odpthread_params_t *thr_params + ); + static struct { int proc; /* true when process mode is required, false otherwise */ } helper_options; -static void *odp_run_start_routine(void *arg) +void *_odph_run_start_routine(void *arg) { odph_linux_thr_params_t *thr_params = arg; @@ -48,206 +47,11 @@ static void *odp_run_start_routine(void *arg) return ret_ptr; } -int odph_linux_pthread_create(odph_linux_pthread_t *pthread_tbl, - const odp_cpumask_t *mask, - const odph_linux_thr_params_t *thr_params) -{ - int i; - int num; - int cpu_count; - int cpu; - int ret; - - num = odp_cpumask_count(mask); - - memset(pthread_tbl, 0, num * sizeof(odph_linux_pthread_t)); - - cpu_count = odp_cpu_count(); - - if (num < 1 || num > cpu_count) { - ODPH_ERR("Invalid number of threads:%d (%d cores available)\n", - num, cpu_count); - return 0; - } - - cpu = odp_cpumask_first(mask); - for (i = 0; i < num; i++) { - cpu_set_t cpu_set; - - CPU_ZERO(&cpu_set); - CPU_SET(cpu, &cpu_set); - - pthread_attr_init(&pthread_tbl[i].attr); - - pthread_tbl[i].cpu = cpu; - - pthread_attr_setaffinity_np(&pthread_tbl[i].attr, - sizeof(cpu_set_t), &cpu_set); - - pthread_tbl[i].thr_params.start = thr_params->start; - pthread_tbl[i].thr_params.arg = thr_params->arg; - pthread_tbl[i].thr_params.thr_type = thr_params->thr_type; - pthread_tbl[i].thr_params.instance = thr_params->instance; - - ret = pthread_create(&pthread_tbl[i].thread, - &pthread_tbl[i].attr, - odp_run_start_routine, - &pthread_tbl[i].thr_params); - if (ret != 0) { - ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); - break; - } - - cpu = odp_cpumask_next(mask, cpu); - } - - return i; -} - -void odph_linux_pthread_join(odph_linux_pthread_t *thread_tbl, int num) -{ - int i; - int ret; - - for (i = 0; i < num; i++) { - /* Wait thread to exit */ - ret = pthread_join(thread_tbl[i].thread, NULL); - if (ret != 0) { - ODPH_ERR("Failed to join thread from cpu #%d\n", - thread_tbl[i].cpu); - } - pthread_attr_destroy(&thread_tbl[i].attr); - } -} - -int odph_linux_process_fork_n(odph_linux_process_t *proc_tbl, - const odp_cpumask_t *mask, - const odph_linux_thr_params_t *thr_params) -{ - pid_t pid; - int num; - int cpu_count; - int cpu; - int i; - - num = odp_cpumask_count(mask); - - memset(proc_tbl, 0, num * sizeof(odph_linux_process_t)); - - cpu_count = odp_cpu_count(); - - if (num < 1 || num > cpu_count) { - ODPH_ERR("Bad num\n"); - return -1; - } - - cpu = odp_cpumask_first(mask); - for (i = 0; i < num; i++) { - cpu_set_t cpu_set; - - CPU_ZERO(&cpu_set); - CPU_SET(cpu, &cpu_set); - - pid = fork(); - - if (pid < 0) { - ODPH_ERR("fork() failed\n"); - return -1; - } - - /* Parent continues to fork */ - if (pid > 0) { - proc_tbl[i].pid = pid; - proc_tbl[i].cpu = cpu; - - cpu = odp_cpumask_next(mask, cpu); - continue; - } - - /* Child process */ - - /* Request SIGTERM if parent dies */ - prctl(PR_SET_PDEATHSIG, SIGTERM); - /* Parent died already? */ - if (getppid() == 1) - kill(getpid(), SIGTERM); - - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { - ODPH_ERR("sched_setaffinity() failed\n"); - return -2; - } - - if (odp_init_local(thr_params->instance, - thr_params->thr_type)) { - ODPH_ERR("Local init failed\n"); - return -2; - } - - return 0; - } - - return 1; -} - -int odph_linux_process_fork(odph_linux_process_t *proc, int cpu, - const odph_linux_thr_params_t *thr_params) -{ - odp_cpumask_t mask; - - odp_cpumask_zero(&mask); - odp_cpumask_set(&mask, cpu); - return odph_linux_process_fork_n(proc, &mask, thr_params); -} - -int odph_linux_process_wait_n(odph_linux_process_t *proc_tbl, int num) -{ - pid_t pid; - int i, j; - int status = 0; - - for (i = 0; i < num; i++) { - pid = wait(&status); - - if (pid < 0) { - ODPH_ERR("wait() failed\n"); - return -1; - } - - for (j = 0; j < num; j++) { - if (proc_tbl[j].pid == pid) { - proc_tbl[j].status = status; - break; - } - } - - if (j == num) { - ODPH_ERR("Bad pid:%d\n", (int)pid); - return -1; - } - - /* Examine the child process' termination status */ - if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) { - ODPH_ERR("Child exit status:%d (pid:%d)\n", - WEXITSTATUS(status), (int)pid); - return -1; - } - if (WIFSIGNALED(status)) { - int signo = WTERMSIG(status); - - ODPH_ERR("Child term signo:%d - %s (pid:%d)\n", - signo, strsignal(signo), (int)pid); - return -1; - } - } - - return 0; -} - /* * wrapper for odpthreads, either implemented as linux threads or processes. * (in process mode, if start_routine returns NULL, the process return FAILURE). */ -static void *odpthread_run_start_routine(void *arg) +void *_odph_thread_run_start_routine(void *arg) { int status; int ret; @@ -289,54 +93,6 @@ static void *odpthread_run_start_routine(void *arg) } /* - * Create a single ODPthread as a linux process - */ -static int odph_linux_process_create(odph_odpthread_t *thread_tbl, - int cpu, - const odph_odpthread_params_t *thr_params) -{ - cpu_set_t cpu_set; - pid_t pid; - - CPU_ZERO(&cpu_set); - CPU_SET(cpu, &cpu_set); - - thread_tbl->start_args.thr_params = *thr_params; /* copy */ - thread_tbl->start_args.linuxtype = ODPTHREAD_PROCESS; - thread_tbl->cpu = cpu; - - pid = fork(); - if (pid < 0) { - ODPH_ERR("fork() failed\n"); - thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; - return -1; - } - - /* Parent continues to fork */ - if (pid > 0) { - thread_tbl->proc.pid = pid; - return 0; - } - - /* Child process */ - - /* Request SIGTERM if parent dies */ - prctl(PR_SET_PDEATHSIG, SIGTERM); - /* Parent died already? */ - if (getppid() == 1) - kill(getpid(), SIGTERM); - - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { - ODPH_ERR("sched_setaffinity() failed\n"); - return -2; - } - - odpthread_run_start_routine(&thread_tbl->start_args); - - return 0; /* never reached */ -} - -/* * Create a single ODPthread as a linux thread */ static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, @@ -361,7 +117,7 @@ static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, ret = pthread_create(&thread_tbl->thread.thread_id, &thread_tbl->thread.attr, - odpthread_run_start_routine, + _odph_thread_run_start_routine, &thread_tbl->start_args); if (ret != 0) { ODPH_ERR("Failed to start thread on cpu #%d\n", cpu); @@ -405,9 +161,9 @@ int odph_odpthreads_create(odph_odpthread_t *thread_tbl, thr_params)) break; } else { - if (odph_linux_process_create(&thread_tbl[i], - cpu, - thr_params)) + if (_odph_linux_process_create(&thread_tbl[i], + cpu, + thr_params)) break; } @@ -677,3 +433,51 @@ int odph_parse_options(int argc, char *argv[], return res; } + +/* + * Create a single ODPthread as a linux process + */ +static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, + int cpu, + const odph_odpthread_params_t *thr_params) +{ + cpu_set_t cpu_set; + pid_t pid; + + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + + thread_tbl->start_args.thr_params = *thr_params; /* copy */ + thread_tbl->start_args.linuxtype = ODPTHREAD_PROCESS; + thread_tbl->cpu = cpu; + + pid = fork(); + if (pid < 0) { + ODPH_ERR("fork() failed\n"); + thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; + return -1; + } + + /* Parent continues to fork */ + if (pid > 0) { + thread_tbl->proc.pid = pid; + return 0; + } + + /* Child process */ + + /* Request SIGTERM if parent dies */ + prctl(PR_SET_PDEATHSIG, SIGTERM); + /* Parent died already? */ + if (getppid() == 1) + kill(getpid(), SIGTERM); + + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set)) { + ODPH_ERR("sched_setaffinity() failed\n"); + return -2; + } + + _odph_thread_run_start_routine(&thread_tbl->start_args); + + return 0; /* never reached */ +} diff --git a/pkgconfig/libodphelper-linux.pc.in b/pkgconfig/libodphelper-linux-generic.pc.in similarity index 72% rename from pkgconfig/libodphelper-linux.pc.in rename to pkgconfig/libodphelper-linux-generic.pc.in index 3987f4c..cab7be2 100644 --- a/pkgconfig/libodphelper-linux.pc.in +++ b/pkgconfig/libodphelper-linux-generic.pc.in @@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: libodphelper-linux +Name: libodphelper-linux-generic Description: Helper for the ODP packet processing engine Version: @PKGCONFIG_VERSION@ -Libs: -L${libdir} -lodphelper-linux +Libs: -L${libdir} -lodphelper-linux-generic Libs.private: Cflags: -I${includedir} diff --git a/test/Makefile.inc b/test/Makefile.inc index 1ebc047..243a616 100644 --- a/test/Makefile.inc +++ b/test/Makefile.inc @@ -4,7 +4,7 @@ LIB = $(top_builddir)/lib #in the following line, the libs using the symbols should come before #the libs containing them! The includer is given a chance to add things #before libodp by setting PRE_LDADD before the inclusion. -LDADD = $(PRE_LDADD) $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la +LDADD = $(PRE_LDADD) $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la INCFLAGS = \ -I$(top_builddir)/platform/@with_platform@/include \ diff --git a/test/common_plat/validation/api/Makefile.inc b/test/common_plat/validation/api/Makefile.inc index ffba620..a0afd26 100644 --- a/test/common_plat/validation/api/Makefile.inc +++ b/test/common_plat/validation/api/Makefile.inc @@ -13,4 +13,4 @@ AM_LDFLAGS += -static LIBCUNIT_COMMON = $(COMMON_DIR)/libcunit_common.la LIBCPUMASK_COMMON = $(COMMON_DIR)/libcpumask_common.la LIBTHRMASK_COMMON = $(COMMON_DIR)/libthrmask_common.la -LIBODP = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la +LIBODP = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la diff --git a/test/linux-generic/Makefile.inc b/test/linux-generic/Makefile.inc index 36745fe..2a49076 100644 --- a/test/linux-generic/Makefile.inc +++ b/test/linux-generic/Makefile.inc @@ -6,7 +6,7 @@ AM_LDFLAGS += -static LIBCUNIT_COMMON = $(top_builddir)/test/common_plat/common/libcunit_common.la LIB = $(top_builddir)/lib -LIBODP = $(LIB)/libodphelper-linux.la $(LIB)/libodp-linux.la +LIBODP = $(LIB)/libodphelper-@with_helper_platform@.la $(LIB)/libodp-linux.la INCCUNIT_COMMON = -I$(top_srcdir)/test/common_plat/common INCODP = \
Only the portable api is built by default, use --enable-helper-extn to enable non portable APIs for a helper platform Signed-off-by: Mike Holmes <mike.holmes@linaro.org> --- configure.ac | 17 +- example/Makefile.inc | 2 +- helper/Makefile.am | 15 +- .../helper/platform/linux-generic/threads_extn.h | 112 ++++++++ helper/include/odp/helper/threads.h | 76 ----- helper/m4/configure.m4 | 11 + helper/odph_thread_internal.h | 27 ++ helper/platform/linux-generic/thread.c | 256 +++++++++++++++++ helper/test/Makefile.am | 17 +- helper/test/linux-generic/Makefile.am | 5 + helper/test/{ => linux-generic}/process.c | 2 +- helper/test/{ => linux-generic}/thread.c | 2 +- helper/threads.c | 314 ++++----------------- ...inux.pc.in => libodphelper-linux-generic.pc.in} | 4 +- test/Makefile.inc | 2 +- test/common_plat/validation/api/Makefile.inc | 2 +- test/linux-generic/Makefile.inc | 2 +- 17 files changed, 515 insertions(+), 351 deletions(-) create mode 100644 helper/include/odp/helper/platform/linux-generic/threads_extn.h create mode 100644 helper/odph_thread_internal.h create mode 100644 helper/platform/linux-generic/thread.c create mode 100644 helper/test/linux-generic/Makefile.am rename helper/test/{ => linux-generic}/process.c (97%) rename helper/test/{ => linux-generic}/thread.c (97%) rename pkgconfig/{libodphelper-linux.pc.in => libodphelper-linux-generic.pc.in} (72%) -- 2.9.3