diff options
author | Matias Elo <matias.elo@nokia.com> | 2018-12-05 13:41:25 +0200 |
---|---|---|
committer | Matias Elo <matias.elo@nokia.com> | 2018-12-05 13:41:25 +0200 |
commit | f0eb4455f4e56b7a427a931647360035f0a21e4d (patch) | |
tree | 6b2e771ae9572a743df7ed3b77a2c6df5a66b6cb /helper | |
parent | 8c63fb0dc5b94dc5a1e6384be97229fa73619ce2 (diff) | |
parent | ec5066a3430e31a87727ac4aea5793253e5ee843 (diff) |
Merge tag 'v1.20.0.0' of https://github.com/Linaro/odp into odp-dpdk
== OpenDataPlane (1.20.0.0)
=== Summary of Changes
ODP v1.20.0.0 is a refresh of ODP, incorporating significant configurability
and performance improvements as well as new APIs and API restructures.
==== APIs
===== Symbol `ODP_SHM_NULL` Removed.
An invalid `odp_shm_t` has the value `ODP_SHM_INVALID`, consistent with other
ODP types. The legacy synonym `ODP_SHM_NULL` is now removed for consistency.
===== New 3GPP Crypto Algorithm Support
New support for 3GPP crypto algorithms is added by defining symbols for
* `ODP_CIPHER_ALG_KASUMI_F8`
* `ODP_CIPHER_ALG_SNOW3G_UEA2`
* `ODP_CIPHER_ALG_ZUC_EEA3`
In addition new authentication algorithm symbols are defined for
* `ODP_AUTH_ALG_KASUMI_F9`
* `ODP_AUTH_ALG_SNOW3G_UIA2`
* `ODP_AUTH_ALG_ZUC_EIA3`
These values are returned as ODP capabilities as well as being accepted in
crypto session creation for implementations that indicate support for them.
===== Crypto Capability for Bitwise Operation
The new `bit_mode` capability Boolean is added to the
`odp_crypto_cipher_capability_t` struct to indicate that an implementation
supports operating in bit mode. When operating in bit
mode, field offsets and lengths are expressed in terms of bits rather than
bytes. However, such lengths must always be specified in multiples of 8.
===== Improved Crypto Spec Documentation
The ODP crypto API specification is tightened to specify default values for
cipher and authentication algorithms. Also documented when key and IV
parameters need to be set.
===== IPsec Extensions
IPsec requires "salt" (extra keying material) when the GMAC authentication
algorithm is used. To accommodate this the `auth_key_extra` field is added to
the `odp_ipsec_crypto_param_t` struct and documentation is added clarifying
when this field is needed and how it should be used.
===== Classifier Type Rename
The `odp_pmr_t` type name for an invalid value is renamed from `ODP_PMR_INVAL`
to `ODP_PMR_INVALID` for consistency with the rest of ODP type names. The old
symbol is still available when ODP is configured with
`--enable-deprecated`.
===== New API for Packet Event Subtypes
The `odp_packet_subtype()` API is added that returns the subtype of a packet
event directly.
===== Streamlined Packet Parsing Results
The `odp_packet_parse_result()` API is added that returns the result of
packet parsing as a single `odp_packet_parse_result_t` struct. This can
offer efficiency improvements for applications that need all parse results
rather than making individual parse result calls.
===== PktIO Extensions to Support per-Queue Configuration
PktIO interfaces support multiple input queues to enable increased parallelism
in I/O processing. Previously, all of these input queues were required to
belong to the same scheduler group. The `odp_pktin_queue_param_t` struct is
now extended with an optional `odp_pktin_queue_param_ovr_t` struct that
permits individual pktin queues to be assigned to separate scheduler groups.
This may permit improved performance for advanced application use cases.
===== Timer Pool Capabilities
The `odp_timer_capability_t` struct is extended to return three additional
pieces of information:
`max_pools_combined`::
The total number of timer pools that can be created combining different
clock sources
`max_pools`::
The maximum number of timer pools for a given clock source.
`max_timers`::
The maximum number of timers in a single pool. A zero value means number is
limited only by available memory.
===== Add Scheduler mix/max/default Priority Functions
Three new APIs: `odp_schedule_max_prio()`, `odp_schedule_min_prio()`, and
`odp_schedule_default_prio()` are added that return the min, max, and default
values specified for the `prio` field in the `odp_schedule_param_t` struct.
With the introduction of these scheduling priority functions the previously
defined macros (`ODP_SCHED_PRIO_HIGHEST`, `ODP_SCHED_PRIO_NORMAL`, and
`ODP_SCHED_PRIO_LOWEST`) are now deprecated and should no longer be used.
===== Specification of `odp_schedule_prio_t` as an `int`
Previously, the `odp_schedule_prio_t` type definition was left to each
implementation. With the addition of explicit schedule priority ranges, this
type is now specified to be an `int` to permit efficient implementation
(including inlining) of these functions.
====== New Scheduler APIs
The new scheduler APIs `odp_schedule_multi_wait()` and
`odp_schedule_multi_no_wait()` are added to provide more efficiently
implementable versions of these functions. The existing scheduler APIs remain
unchanged. These new APIs can simply provide a fastpath for some
applications/implementations as an alternative to specifying a parameter on
`odp_schedule_multi()`.
===== Memory Model in `odp_init_global()`
The `odp_init_t` parameter passed to `odp_init_global()` is extended to
add the `mem_model` field. This field is defined by the new `odp_mem_model_t`
struct and is used to specify whether the application will be using a
thread (`ODP_MEM_MODEL_THREAD`) or process (`ODP_MEM_MODEL_PROCESS`)
memory model. The default is a thread model is used for compatibility with
previous levels of ODP.
==== ABI Changes
A number of changes to the ODP ABI have also been made in this release to
improve application binary portability.
===== Strong Typing for Timer Pools
The `odp_timer_pool_t` is now strongly typed.
===== Consistent Initialization
The values of the various `ODP_xxx_INVALID` symbols for ODP abstract types in
the `odp-linux` reference implementation are now consistently zeros. This
reduces errors and improves portability.
=== Implementation Improvements
==== Configuration File
A new configuration file mechanism is introduced that makes use of
https://www.hyperrealm.com/libconfig/libconfig_manual.html[libconfig] to
enable various runtime ODP parameters to be specified dynamically.
Default configuration values for the `odp-linux` reference implementation are
contained in the `config/odp-linux-generic.conf` file. Users may override
these default values by supplying their own configuration file. At
`odp_init_global()` time, if the `ODP_CONFIG_FILE` environment variable is set,
this is used to locate the path to the override configuration file.
==== Process Mode Support
The `odp-linux` reference implementation now supports applications that run in
process mode (`mem_model` = `ODP_MEM_MODEL_PROCESS`) as well as the default
thread mode. This support only applies within a single ODP instance, so any
`fork()` calls must be done only _after_ `odp_init_global()` has been called
to initialize ODP on a root process.
==== Removal of `iQuery` Scheduler
The `iQuery` scheduler is removed from the `odp-linux` reference
implementation, as it offers no performance advantages and has not seen
application use.
==== Number of CPUs
The `odp-linux` reference implementation now supports up to 256 CPUs by
default (increased from 128).
==== Support for Large Burst Sizes
The `odp-linux` reference implementation now supports large burst sizes for
both I/O and non-I/O scheduled events. Large bursts (when available) are
received directly to the application without any stashing for improved
throughput. Burst sizes are configurable via the new configuration file
mechanism, as described above.
==== `--without-openssl` Warnings
When building `odp-linux` using `--without-openssl` a warning will be issued
cautioning that strong cryptography will not be available.
==== Inline Queue Enq/Deq APIs
The various enq/deq APIs are now subject to inlining when `odp-linux` is
built with `--disable-abi-compat`.
==== Configurable Timer Controls
Inline timers are now controlled via a config file option. Timer polling
frequency is similarly controlled via the config file.
==== Huge Page Configuration
The config file is now used to specify the huge page usage limit.
==== Single and Multi-Consumer/Producer Rings
The queue implementation in `odp-linux` now automatically makes use of
optimized single and multi-consumer/producer rings to significantly speed
up enq/deq processing.
==== `odp_shm_print_all()` Improvements
The output from `odp_shm_print_all()` is reworked to provide more useful
and comprehensive shared memory usage information in `odp-linux`.
==== IPsec Improvements
SA lifetime checking is now more scalable to multiple threads. This
significantly reduces overhead for multithreaded IPsec applications.
==== Native Builds
When running in non-ABI compatibility mode, `odp-linux` now enables
native machine-specific optimizations for the CPU architecture of the
local machine.
=== Validation Test Improvements
==== SCTP Test Packets
SCTP test packets are now used in parser testing. SCTP headers are added to
ODP and ODP helpers and SCTP checksums are now inserted and verified as part
of validation testing.
==== `odp_packet_reset()` Test
The packet validation test suite now properly tests `odp_packet_reset()`.
=== Helper Changes
In support of process mode, ODP helper functions have been changed to
better match these new capabilities
==== New `enum`
The `odph_linux_thread_type_t enum` has been replaced with the new
`odp_mem_model_t` type.
==== Helper Options
The new `odph_options()` getter function is added that returns
applicable options in effect via the new `odph_helper_options_t` struct.
This currently includes the memory model (thread or process) that is in use.
==== SCTP Helpers
The new helper APIs `odph_sctp_chksum_set()` and `odph_sctp_chksum_verify()`
are added to facilitate working with SCTP packet checksums.
=== Performance Test Improvements
==== Pool Performance
A new `odp_pool_perf` test has been added that stress-tests ODP pool
functions in a multithreaded environment to generate performance statistics.
==== Scheduler Performance
A new `odp_sched_perf` test has been added that stress-tests the scheduler
in a multithreaded environment.
==== CPU Performance
A new `odp_cpu_bench` performance test has been added that runs
compute-intensive packet operations in a multithreaded environment and prints
the observed maximum throughput for each thread.
=== Example Improvements
==== Classifier Example changes
The `odp_classifier` example program now uses a reduced number of threads by
default to reduce elapsed run time. `ODP_THREAD_COUNT_MAX` is also now used as
the max worker count.
==== Generator Improvements
The `odp_generator` example has numerous cleanups and performance improvements.
==== IPsec Example
The `odp_ipsec` example now properly stops and closes pktio devices on exit.
==== Packet Dumping
A new `odp_packet_dump` example is added that prints received packets to the
terminal. This is useful for debugging packet I/O interfaces.
==== Sysinfo Example
A new `odp_sysinfo` example is provided that prints system information. Useful
for checking the ODP environment during debugging. This includes providing
detailed information about the various crypto facilities supported, as well
as the feature flags used at build time (_e.g.,_ if the binary was built with
ARMv8.0 or ARMv8.1 instructions).
==== Traffic Manager Example
The traffic manager example now properly destroys all TM queues it creates
for improved reliability. It also now always prints a proper termination
summary message.
=== Bug Fixes
==== Numbered Bugs/Issues
===== https://bugs.linaro.org/show_bug.cgi?id=3983[Bug 3983]
Compile fails on OpenSuSE 42.2 Leap with error: negative width in bit field
'__error_if_negative'
===== https://bugs.linaro.org/show_bug.cgi?id=3989[Bug 3989]
odp_system_info_init() issues
===== https://bugs.linaro.org/show_bug.cgi?id=3999[Bug 3999]
IPsec antireplay check drops packets when sequence number jumps.
===== https://bugs.linaro.org/show_bug.cgi?id=4002[Bug 4002]
IPsec SA creation must fail for ESN-enabled SAs
===== https://bugs.linaro.org/show_bug.cgi?id=4013[Bug 4013]
Per-SA IPv4 ID allocation may cause duplicate IDs.
===== https://bugs.linaro.org/show_bug.cgi?id=4017[Bug 4017]
Unexpected IP ID causes IPsec API validation to fail
===== https://github.com/Linaro/odp/issues/662[Issue 662]
rte_mempool_ops_alloc() is not dpdk api
==== Unnumbered Bugs/Issues
* Fixed enq/deq issues encountered on architectures with weak memory ordering.
* Return 0 from `odp_sys_huge_page_size_all()` if hugepages are not
supported/detected. Tests modified to not treat this as an error.
* Set `ODP_CACHE_LINE_SIZE` to 128 on ppc64le systems.
* iplookuptable fix putting values into table
* DPDK pktio support now works properly across multiple ODP instances.
* Zero timer pool memory on reserve (fixes timer failures due to uninitialized
variables).
* `-march=native` disabled for `clang`. This fixes a known issue with recent
levels of clang.
=== Known Issues
==== https://bugs.linaro.org/show_bug.cgi?id=3998[Bug 3998]
IPsec extended sequence number support is missing
==== https://bugs.linaro.org/show_bug.cgi?id=4014[Bug 4014]
Separate IP ID allocation for transport and tunnel mode SAs may cause
duplicate IDs
==== https://bugs.linaro.org/show_bug.cgi?id=4018[Bug 4018]
Unexpected IV causes IPsec API validation to fail
==== https://bugs.linaro.org/show_bug.cgi?id=4040[Bug 4040]
Clang build fails on Ubuntu 18.04
# Conflicts:
# .travis.yml
# example/packet/Makefile.am
Diffstat (limited to 'helper')
-rw-r--r-- | helper/include/odp/helper/threads.h | 26 | ||||
-rw-r--r-- | helper/iplookuptable.c | 73 | ||||
-rw-r--r-- | helper/test/odpthreads.c | 13 | ||||
-rw-r--r-- | helper/threads.c | 70 |
4 files changed, 129 insertions, 53 deletions
diff --git a/helper/include/odp/helper/threads.h b/helper/include/odp/helper/threads.h index 9d03c7192..6cee2522d 100644 --- a/helper/include/odp/helper/threads.h +++ b/helper/include/odp/helper/threads.h @@ -54,13 +54,6 @@ typedef struct { int status; /**< Process state change status */ } odph_linux_process_t; -/** odpthread linux type: whether an ODP thread is a linux thread or process */ -typedef enum odph_odpthread_linuxtype_e { - ODPTHREAD_NOT_STARTED = 0, - ODPTHREAD_PROCESS, - ODPTHREAD_PTHREAD -} odph_odpthread_linuxtype_t; - /** odpthread parameters for odp threads (pthreads and processes) */ typedef struct { int (*start)(void *); /**< Thread entry point function */ @@ -71,7 +64,7 @@ typedef struct { /** The odpthread starting arguments, used both in process or thread mode */ typedef struct { - odph_odpthread_linuxtype_t linuxtype; /**< process or pthread */ + odp_mem_model_t mem_model; /**< process or thread */ odph_odpthread_params_t thr_params; /**< odpthread start parameters */ } odph_odpthread_start_args_t; @@ -95,6 +88,11 @@ typedef struct { }; } odph_odpthread_t; +/** Linux helper options */ +typedef struct { + odp_mem_model_t mem_model; /**< Process or thread */ +} odph_helper_options_t; + /** * Creates and launches odpthreads (as linux threads or processes) * @@ -161,6 +159,18 @@ int odph_odpthread_getaffinity(void); int odph_parse_options(int argc, char *argv[]); /** + * Get linux helper options + * + * Return used ODP helper options. odph_parse_options() must be called before + * using this function. + * + * @param[out] options ODP helper options + * + * @return 0 on success, -1 on failure + */ +int odph_options(odph_helper_options_t *options); + +/** * @} */ diff --git a/helper/iplookuptable.c b/helper/iplookuptable.c index 61f634022..84b4e2cbb 100644 --- a/helper/iplookuptable.c +++ b/helper/iplookuptable.c @@ -83,9 +83,9 @@ typedef struct trie_node { } trie_node_t; /** Number of L2\L3 entries(subtrees) per cache cube. */ -#define CACHE_NUM_SUBTREE (1 << 13) +#define CACHE_NUM_SUBTREE (4 * 1024) /** Number of trie nodes per cache cube. */ -#define CACHE_NUM_TRIE (1 << 20) +#define CACHE_NUM_TRIE (4 * 1024) /** @typedef cache_type_t * Cache node type @@ -187,12 +187,34 @@ cache_alloc_new_pool( { odp_pool_t pool; odp_pool_param_t param; + odp_pool_capability_t pool_capa; odp_queue_t queue = tbl->free_slots[type]; odp_buffer_t buffer; char pool_name[ODPH_TABLE_NAME_LEN + 8]; uint32_t size = 0, num = 0; + if (odp_pool_capability(&pool_capa)) { + ODPH_ERR("pool capa failed\n"); + return -1; + } + + if (pool_capa.buf.max_num) { + if (pool_capa.buf.max_num < CACHE_NUM_TRIE || + pool_capa.buf.max_num < CACHE_NUM_SUBTREE) { + ODPH_ERR("pool size too small\n"); + return -1; + } + } + + if (pool_capa.buf.max_size) { + if (pool_capa.buf.max_size < ENTRY_SIZE * ENTRY_NUM_SUBTREE || + pool_capa.buf.max_size < sizeof(trie_node_t)) { + ODPH_ERR("buffer size too small\n"); + return -1; + } + } + /* Create new pool (new free buffers). */ odp_pool_param_init(¶m); param.type = ODP_POOL_BUFFER; @@ -223,7 +245,11 @@ cache_alloc_new_pool( while ((buffer = odp_buffer_alloc(pool)) != ODP_BUFFER_INVALID) { cache_init_buffer(buffer, type, size); - odp_queue_enq(queue, odp_buffer_to_event(buffer)); + if (odp_queue_enq(queue, odp_buffer_to_event(buffer))) { + ODPH_DBG("queue enqueue failed\n"); + odp_buffer_free(buffer); + break; + } } tbl->cache_count[type]++; @@ -449,10 +475,28 @@ odph_table_t odph_iplookup_table_create(const char *name, odp_shm_t shm_tbl; odp_queue_t queue; odp_queue_param_t qparam; + odp_queue_capability_t queue_capa; unsigned i; - uint32_t impl_size, l1_size; + uint32_t impl_size, l1_size, queue_size; char queue_name[ODPH_TABLE_NAME_LEN + 2]; + if (odp_queue_capability(&queue_capa)) { + ODPH_ERR("queue capa failed\n"); + return NULL; + } + + if (queue_capa.plain.max_size) { + if (queue_capa.plain.max_size < CACHE_NUM_TRIE || + queue_capa.plain.max_size < CACHE_NUM_SUBTREE) { + ODPH_ERR("queue size too small\n"); + return NULL; + } + } + + queue_size = CACHE_NUM_TRIE; + if (CACHE_NUM_SUBTREE > CACHE_NUM_TRIE) + queue_size = CACHE_NUM_SUBTREE; + /* Check for valid parameters */ if (strlen(name) == 0) { ODPH_DBG("invalid parameters\n"); @@ -502,6 +546,7 @@ odph_table_t odph_iplookup_table_create(const char *name, odp_queue_param_init(&qparam); qparam.type = ODP_QUEUE_TYPE_PLAIN; + qparam.size = queue_size; sprintf(queue_name, "%s_%d", name, i); queue = odp_queue_create(queue_name, &qparam); if (queue == ODP_QUEUE_INVALID) { @@ -585,24 +630,25 @@ prefix_insert_into_lx( odph_iplookup_table_impl *tbl, prefix_entry_t *entry, uint8_t cidr, odp_buffer_t nexthop, uint8_t level) { - uint8_t ret = 0; + int ret = 0; uint32_t i = 0, limit = (1 << (level - cidr)); prefix_entry_t *e = entry, *ne = NULL; for (i = 0; i < limit; i++, e++) { - if (e->child == 1) { - if (e->cidr > cidr) - continue; + if (e->cidr > cidr) + continue; + if (e->child == 1) { e->cidr = cidr; /* push to next level */ ne = (prefix_entry_t *)e->ptr; ret = prefix_insert_into_lx( tbl, ne, cidr, nexthop, cidr + 8); + if (ret == -1) + return -1; + if (ret == 0) + return ret; } else { - if (e->cidr > cidr) - continue; - e->child = 0; e->cidr = cidr; e->nexthop = nexthop; @@ -678,8 +724,9 @@ odph_iplookup_table_put_value(odph_table_t tbl, void *key, void *value) nexthop = *((odp_buffer_t *)value); - if (prefix->cidr == 0) + if (prefix->cidr == 0 || prefix->cidr > 32) return -1; + prefix->ip = prefix->ip & (0xffffffff << (IP_LENGTH - prefix->cidr)); /* insert into trie */ @@ -899,7 +946,7 @@ odph_iplookup_table_remove_value(odph_table_t tbl, void *key) ip = prefix->ip; cidr = prefix->cidr; - if (cidr == 0) + if (cidr == 0 || cidr > 32) return -EINVAL; prefix_entry_t *entry = &impl->l1e[ip >> 16]; diff --git a/helper/test/odpthreads.c b/helper/test/odpthreads.c index ad48ec2d5..55db37e0d 100644 --- a/helper/test/odpthreads.c +++ b/helper/test/odpthreads.c @@ -64,18 +64,27 @@ static int worker_fn(void *arg ODPH_UNUSED) /* Create additional dataplane opdthreads */ int main(int argc, char *argv[]) { + odph_helper_options_t helper_options; odph_odpthread_params_t thr_params; odph_odpthread_t thread_tbl[NUMBER_WORKERS]; odp_cpumask_t cpu_mask; + odp_init_t init_param; int num_workers; int cpu, affinity; int ret; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; - /* let helper collect its own arguments (e.g. --odph_proc) */ + /* Let helper collect its own arguments (e.g. --odph_proc) */ argc = odph_parse_options(argc, argv); + if (odph_options(&helper_options)) { + ODPH_ERR("Error: reading ODP helper options failed.\n"); + exit(EXIT_FAILURE); + } + + odp_init_param_init(&init_param); + init_param.mem_model = helper_options.mem_model; - if (odp_init_global(&odp_instance, NULL, NULL)) { + if (odp_init_global(&odp_instance, &init_param, NULL)) { ODPH_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } diff --git a/helper/threads.c b/helper/threads.c index 86d6bf7be..01bc33eac 100644 --- a/helper/threads.c +++ b/helper/threads.c @@ -10,6 +10,7 @@ #define _GNU_SOURCE #endif #include <sched.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> @@ -20,9 +21,9 @@ #include <odp/helper/threads.h> #include "odph_debug.h" -static struct { - int proc; /* true when process mode is required, false otherwise */ -} helper_options; +#define FAILED_CPU -1 + +static odph_helper_options_t helper_options; /* * wrapper for odpthreads, either implemented as linux threads or processes. @@ -41,7 +42,7 @@ static void *_odph_thread_run_start_routine(void *arg) /* ODP thread local init */ if (odp_init_local(thr_params->instance, thr_params->thr_type)) { ODPH_ERR("Local init failed\n"); - if (start_args->linuxtype == ODPTHREAD_PROCESS) + if (start_args->mem_model == ODP_MEM_MODEL_PROCESS) _exit(EXIT_FAILURE); return (void *)-1; } @@ -49,7 +50,7 @@ static void *_odph_thread_run_start_routine(void *arg) ODPH_DBG("helper: ODP %s thread started as linux %s. (pid=%d)\n", thr_params->thr_type == ODP_THREAD_WORKER ? "worker" : "control", - (start_args->linuxtype == ODPTHREAD_PTHREAD) ? + (start_args->mem_model == ODP_MEM_MODEL_THREAD) ? "pthread" : "process", (int)getpid()); @@ -60,7 +61,7 @@ static void *_odph_thread_run_start_routine(void *arg) ODPH_ERR("Local term failed\n"); /* for process implementation of odp threads, just return status... */ - if (start_args->linuxtype == ODPTHREAD_PROCESS) + if (start_args->mem_model == ODP_MEM_MODEL_PROCESS) _exit(status); /* threads implementation return void* pointers: cast status to that. */ @@ -80,14 +81,14 @@ static int _odph_linux_process_create(odph_odpthread_t *thread_tbl, 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->start_args.thr_params = *thr_params; /* copy */ + thread_tbl->start_args.mem_model = ODP_MEM_MODEL_PROCESS; thread_tbl->cpu = cpu; pid = fork(); if (pid < 0) { ODPH_ERR("fork() failed\n"); - thread_tbl->start_args.linuxtype = ODPTHREAD_NOT_STARTED; + thread_tbl->cpu = FAILED_CPU; return -1; } @@ -135,8 +136,8 @@ static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, 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; + thread_tbl->start_args.thr_params = *thr_params; /* copy */ + thread_tbl->start_args.mem_model = ODP_MEM_MODEL_THREAD; ret = pthread_create(&thread_tbl->thread.thread_id, &thread_tbl->thread.attr, @@ -144,7 +145,7 @@ static int odph_linux_thread_create(odph_odpthread_t *thread_tbl, &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; + thread_tbl->cpu = FAILED_CPU; return ret; } @@ -178,7 +179,7 @@ int odph_odpthreads_create(odph_odpthread_t *thread_tbl, cpu = odp_cpumask_first(mask); for (i = 0; i < num; i++) { - if (!helper_options.proc) { + if (helper_options.mem_model == ODP_MEM_MODEL_THREAD) { if (odph_linux_thread_create(&thread_tbl[i], cpu, thr_params)) @@ -214,9 +215,13 @@ int odph_odpthreads_join(odph_odpthread_t *thread_tbl) /* joins linux threads or wait for processes */ do { + if (thread_tbl[i].cpu == FAILED_CPU) { + ODPH_DBG("ODP thread %d not started.\n", i); + continue; + } /* pthreads: */ - switch (thread_tbl[i].start_args.linuxtype) { - case ODPTHREAD_PTHREAD: + if (thread_tbl[i].start_args.mem_model == + ODP_MEM_MODEL_THREAD) { /* Wait thread to exit */ ret = pthread_join(thread_tbl[i].thread.thread_id, &thread_ret); @@ -233,10 +238,7 @@ int odph_odpthreads_join(odph_odpthread_t *thread_tbl) } } pthread_attr_destroy(&thread_tbl[i].thread.attr); - break; - - case ODPTHREAD_PROCESS: - + } else { /* processes: */ pid = waitpid(thread_tbl[i].proc.pid, &status, 0); @@ -262,16 +264,7 @@ int odph_odpthreads_join(odph_odpthread_t *thread_tbl) signo, strsignal(signo), (int)pid); retval = -1; } - break; - - case ODPTHREAD_NOT_STARTED: - ODPH_DBG("No join done on not started ODPthread.\n"); - break; - default: - ODPH_DBG("Invalid case statement value!\n"); - break; } - } while (!thread_tbl[i++].last); return (retval < 0) ? retval : terminated; @@ -332,14 +325,22 @@ int odph_odpthread_getaffinity(void) int odph_parse_options(int argc, char *argv[]) { + char *env; int i, j; - helper_options.proc = 0; + helper_options.mem_model = ODP_MEM_MODEL_THREAD; + + /* Enable process mode using environment variable. Setting environment + * variable is easier for CI testing compared to command line + * argument. */ + env = getenv("ODPH_PROC_MODE"); + if (env && atoi(env)) + helper_options.mem_model = ODP_MEM_MODEL_PROCESS; /* Find and remove option */ for (i = 0; i < argc;) { if (strcmp(argv[i], "--odph_proc") == 0) { - helper_options.proc = 1; + helper_options.mem_model = ODP_MEM_MODEL_PROCESS; for (j = i; j < argc - 1; j++) argv[j] = argv[j + 1]; @@ -353,3 +354,12 @@ int odph_parse_options(int argc, char *argv[]) return argc; } + +int odph_options(odph_helper_options_t *options) +{ + memset(options, 0, sizeof(odph_helper_options_t)); + + options->mem_model = helper_options.mem_model; + + return 0; +} |