#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <getopt.h>
#include <odp/helper/odph_api.h>
#include <export_results.h>
#define NUM_ROUNDS 100000u
#define INIT_VAL 0x80000000
#define DEFAULT_MAX_WORKERS 10
#define TEST_MAX_BENCH 70
#define TEST_INFO(name, test, validate, op_type) \
{name, test, validate, op_type}
typedef void (*test_fn_t)(void *val, void *out, uint32_t num_round);
typedef int (*validate_fn_t)(void *val, void *out, uint32_t num_round,
uint32_t num_worker, int private);
typedef enum {
OP_32BIT,
OP_64BIT,
OP_128BIT
} op_bit_t;
typedef struct test_options_t {
uint32_t num_cpu;
uint32_t num_round;
int private;
} test_options_t;
union {
};
} test_atomic_t;
typedef struct test_global_t test_global_t;
typedef struct test_thread_ctx_t {
test_global_t *global;
test_fn_t func;
uint64_t nsec;
uint64_t cycles;
uint32_t idx;
op_bit_t type;
} test_thread_ctx_t;
typedef struct results_t {
const char *test_name;
double cycles_per_op;
double nsec_per_op;
double operations_per_cpu;
double total_operations;
} results_t;
struct test_global_t {
test_options_t test_options;
union {
};
union {
uint32_t u32;
uint64_t u64;
test_common_options_t common_options;
results_t results[TEST_MAX_BENCH];
};
typedef struct {
const char *name;
test_fn_t test_fn;
validate_fn_t validate_fn;
op_bit_t type;
} test_case_t;
static test_global_t *test_global;
static inline void test_atomic_load_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_load_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_load_u128(void *val, void *out, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++) {
}
*result = ret;
}
static inline int validate_atomic_init_val_u32(void *val, void *out, uint32_t num_round,
{
uint32_t *result = out;
(*result != (uint32_t)INIT_VAL * num_round);
}
static inline int validate_atomic_init_val_u64(void *val, void *out, uint32_t num_round,
{
uint64_t *result = out;
(*result != (uint64_t)INIT_VAL * num_round);
}
static inline int validate_atomic_init_val_u128(void *val, void *out, uint32_t num_round,
{
if (atomic_val.
u64[0] != INIT_VAL || atomic_val.
u64[1] != INIT_VAL)
return -1;
if (result->
u64[0] != (uint64_t)INIT_VAL * num_round ||
result->
u64[1] != (uint64_t)INIT_VAL * num_round)
return -1;
return 0;
}
static inline void test_atomic_store_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_store_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_store_u128(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
new_val.
u64[0] = INIT_VAL + 1;
new_val.
u64[1] = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++) {
}
}
static inline int validate_atomic_num_round_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
}
static inline int validate_atomic_num_round_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
}
static inline int validate_atomic_num_round_u128(
void *val,
void *out
ODP_UNUSED,
{
return (atomic_val.
u64[0] != ((uint64_t)INIT_VAL + num_round) ||
atomic_val.
u64[1] != ((uint64_t)INIT_VAL + num_round));
}
static inline void test_atomic_fetch_add_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_fetch_add_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline int validate_atomic_add_round_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
uint32_t num_worker, int private)
{
if (private)
}
static inline int validate_atomic_add_round_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
uint32_t num_worker, int private)
{
if (private)
}
static inline void test_atomic_add_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_add_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_fetch_sub_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_fetch_sub_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline int validate_atomic_sub_round_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
uint32_t num_worker, int private)
{
if (private)
}
static inline int validate_atomic_sub_round_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
uint32_t num_worker, int private)
{
if (private)
((uint64_t)num_worker * num_round));
}
static inline void test_atomic_sub_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_sub_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_fetch_inc_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_fetch_inc_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_inc_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_inc_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_fetch_dec_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_fetch_dec_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_dec_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_dec_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_max_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_max = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_max_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_max = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline int validate_atomic_max_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
return (result != ((uint32_t)INIT_VAL + num_round)) && (result != UINT32_MAX);
}
static inline int validate_atomic_max_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
return (result != ((uint64_t)INIT_VAL + num_round)) && (result != UINT64_MAX);
}
static inline void test_atomic_fetch_max_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t new_max = INIT_VAL + 1, old_max = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++)
*result = old_max;
}
static inline void test_atomic_fetch_max_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t new_max = INIT_VAL + 1, old_max = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++)
*result = old_max;
}
static inline int validate_atomic_fetch_max_u32(void *val, void *out, uint32_t num_round,
{
uint32_t *output = out;
return (result != ((uint32_t)INIT_VAL + num_round) && result != UINT32_MAX) ||
(*output != result - 1 && *output != result);
}
static inline int validate_atomic_fetch_max_u64(void *val, void *out, uint32_t num_round,
{
uint64_t *output = out;
return (result != ((uint64_t)INIT_VAL + num_round) && result != UINT64_MAX) ||
(*output != result - 1 && *output != result);
}
static inline void test_atomic_min_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_min = INIT_VAL - 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_min_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_min = INIT_VAL - 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline int validate_atomic_min_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
return result != ((uint32_t)INIT_VAL - num_round) && result != 0;
}
static inline int validate_atomic_min_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
return result != ((uint64_t)INIT_VAL - num_round) && result != 0;
}
static inline void test_atomic_fetch_min_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t new_min = INIT_VAL - 1, old_min = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++)
*result = old_min;
}
static inline void test_atomic_fetch_min_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t new_min = INIT_VAL - 1, old_min = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++)
*result = old_min;
}
static inline int validate_atomic_fetch_min_u32(void *val, void *out, uint32_t num_round,
{
uint32_t *output = out;
return (result != ((uint32_t)INIT_VAL - num_round) && result != 0) ||
(*output != result + 1 && *output != result);
}
static inline int validate_atomic_fetch_min_u64(void *val, void *out, uint32_t num_round,
{
uint64_t *output = out;
return (result != ((uint64_t)INIT_VAL - num_round) && result != 0) ||
(*output != result + 1 && *output != result);
}
static inline void test_atomic_cas_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
uint32_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
uint64_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_u128(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
new_val.
u64[0] = INIT_VAL + 1;
new_val.
u64[1] = INIT_VAL + 1;
old_val.
u64[0] = INIT_VAL;
old_val.
u64[1] = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val;
}
}
}
static inline int validate_atomic_cas_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
if (private)
return result != ((uint32_t)INIT_VAL + num_round);
return result > ((uint32_t)INIT_VAL + num_round);
}
static inline int validate_atomic_cas_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
if (private)
return result != ((uint64_t)INIT_VAL + num_round);
return result > ((uint64_t)INIT_VAL + num_round);
}
static inline int validate_atomic_cas_u128(
void *val,
void *out
ODP_UNUSED, uint32_t num_round,
{
if (private)
return (result.
u64[0] != ((uint64_t)INIT_VAL + num_round) ||
result.
u64[1] != ((uint64_t)INIT_VAL + num_round));
return (result.
u64[0] > ((uint64_t)INIT_VAL + num_round) ||
result.
u64[1] > ((uint64_t)INIT_VAL + num_round));
}
static inline void test_atomic_xchg_u32(void *val, void *out, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_xchg_u64(void *val, void *out, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_bit_set_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_fetch_set_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_bit_clr_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_fetch_clr_u32(void *val, void *out, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_bit_set_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_fetch_set_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_bit_clr_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_fetch_clr_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_load_acq_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t *result = out;
uint32_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_load_acq_u64(void *val, void *out, uint32_t num_round)
{
uint64_t *result = out;
uint64_t ret = 0;
for (uint32_t i = 0; i < num_round; i++)
*result = ret;
}
static inline void test_atomic_store_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_store_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_add_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_add_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_sub_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_sub_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_cas_acq_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
uint32_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_acq_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
uint64_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_acq_u128(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
new_val.
u64[0] = INIT_VAL + 1;
new_val.
u64[1] = INIT_VAL + 1;
old_val.
u64[0] = INIT_VAL;
old_val.
u64[1] = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val;
}
}
}
static inline void test_atomic_cas_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
uint32_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
uint64_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_rel_u128(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
new_val.
u64[0] = INIT_VAL + 1;
new_val.
u64[1] = INIT_VAL + 1;
old_val.
u64[0] = INIT_VAL;
old_val.
u64[1] = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val;
}
}
}
static inline void test_atomic_cas_acq_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint32_t new_val = INIT_VAL + 1;
uint32_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_acq_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
uint64_t new_val = INIT_VAL + 1;
uint64_t old_val = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val++;
}
}
static inline void test_atomic_cas_acq_rel_u128(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
new_val.
u64[0] = INIT_VAL + 1;
new_val.
u64[1] = INIT_VAL + 1;
old_val.
u64[0] = INIT_VAL;
old_val.
u64[1] = INIT_VAL;
for (uint32_t i = 0; i < num_round; i++) {
old_val = new_val;
}
}
}
static inline void test_atomic_bit_set_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_clr_rel_u32(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_set_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static inline void test_atomic_bit_clr_rel_u64(
void *val,
void *out
ODP_UNUSED, uint32_t num_round)
{
for (uint32_t i = 0; i < num_round; i++)
}
static void print_usage(void)
{
printf("\n"
"Atomic operations performance test\n"
"\n"
"Usage: odp_atomic_perf [options]\n"
"\n"
" -c, --num_cpu Number of CPUs (worker threads). 0: all available CPUs (or max %d) (default)\n"
" -r, --num_round Number of rounds (default %u)\n"
" -p, --private 0: The same atomic variable is shared between threads (default)\n"
" 1: Atomic variables are private to each thread\n"
" -h, --help This help\n"
"\n", DEFAULT_MAX_WORKERS, NUM_ROUNDS);
}
static void print_info(test_options_t *test_options)
{
printf("\nAtomic operations performance test configuration:\n");
printf(" num cpu %u\n", test_options->num_cpu);
printf(" num rounds %u\n", test_options->num_round);
printf(" private %i\n", test_options->private);
printf("\n");
printf("\nAtomic operations lock-free:\n");
printf(
" odp_atomic_load_u64: %" PRIu32
"\n", atomic_ops.
op.
load);
printf(
" odp_atomic_store_u64: %" PRIu32
"\n", atomic_ops.
op.
store);
printf(
" odp_atomic_fetch_add_u64: %" PRIu32
"\n", atomic_ops.
op.
fetch_add);
printf(
" odp_atomic_add_u64: %" PRIu32
"\n", atomic_ops.
op.
add);
printf(
" odp_atomic_fetch_sub_u64: %" PRIu32
"\n", atomic_ops.
op.
fetch_sub);
printf(
" odp_atomic_sub_u64: %" PRIu32
"\n", atomic_ops.
op.
sub);
printf(
" odp_atomic_fetch_inc_u64: %" PRIu32
"\n", atomic_ops.
op.
fetch_inc);
printf(
" odp_atomic_inc_u64: %" PRIu32
"\n", atomic_ops.
op.
inc);
printf(
" odp_atomic_fetch_dec_u64: %" PRIu32
"\n", atomic_ops.
op.
fetch_dec);
printf(
" odp_atomic_dec_u64: %" PRIu32
"\n", atomic_ops.
op.
dec);
printf(
" odp_atomic_min_u64: %" PRIu32
"\n", atomic_ops.
op.
min);
printf(
" odp_atomic_fetch_min_u64: %" PRIu32
"\n", atomic_ops.
op.
fetch_min);
printf(
" odp_atomic_max_u64: %" PRIu32
"\n", atomic_ops.
op.
max);
printf(
" odp_atomic_fetch_max_u64: %" PRIu32
"\n", atomic_ops.
op.
fetch_max);
printf(
" odp_atomic_cas_u64: %" PRIu32
"\n", atomic_ops.
op.
cas);
printf(
" odp_atomic_xchg_u64: %" PRIu32
"\n", atomic_ops.
op.
xchg);
printf(
" odp_atomic_bit_fetch_set_u64: %" PRIu32
"\n", atomic_ops.
op.
bit_fetch_set);
printf(
" odp_atomic_bit_set_u64: %" PRIu32
"\n", atomic_ops.
op.
bit_set);
printf(
" odp_atomic_bit_fetch_clr_u64: %" PRIu32
"\n", atomic_ops.
op.
bit_fetch_clr);
printf(
" odp_atomic_bit_clr_u64: %" PRIu32
"\n", atomic_ops.
op.
bit_clr);
printf(
" odp_atomic_load_u128: %" PRIu32
"\n", atomic_ops.
op.
load);
printf(
" odp_atomic_store_u128: %" PRIu32
"\n", atomic_ops.
op.
store);
printf(
" odp_atomic_cas_u128: %" PRIu32
"\n", atomic_ops.
op.
cas);
printf("\n\n");
}
static int output_summary(test_global_t *global)
{
int results_size = ODPH_ARRAY_SIZE(global->results);
results_t res;
if (global->common_options.is_export) {
if (test_common_write("function name,ops/cpu (M/s),total ops (M/s),"
"cycles/op,nsec/op\n")) {
test_common_write_term();
return -1;
}
}
printf("Average results over %i threads:\n", global->test_options.num_cpu);
printf("%-33s %-15s %-17s %-11s %-11s\n", "function name", "ops/cpu (M/s)",
"total ops (M/s)", "cycles/op", "nsec/op");
printf("-----------------------------------------------------------------------------"
"-----------------------\n");
for (int i = 0; i < results_size && global->results[i].test_name; i++) {
res = global->results[i];
printf("[%02d] %-28s %-15.2f %-17.2f %-11.2f %-11.2f\n", i + 1,
res.test_name, res.operations_per_cpu, res.total_operations,
res.cycles_per_op, res.nsec_per_op);
if (global->common_options.is_export) {
if (test_common_write("%s,%f,%f,%f,%f\n", res.test_name,
res.operations_per_cpu, res.total_operations,
res.cycles_per_op, res.nsec_per_op)) {
test_common_write_term();
return -1;
}
}
}
if (global->common_options.is_export)
test_common_write_term();
return 0;
}
static int parse_options(int argc, char *argv[], test_options_t *test_options)
{
int opt;
int ret = 0;
static const struct option longopts[] = {
{"num_cpu", required_argument, NULL, 'c'},
{"num_round", required_argument, NULL, 'r'},
{"private", required_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
static const char *shortopts = "+c:r:p:h";
memset(test_options, 0, sizeof(test_options_t));
test_options->num_cpu = 0;
test_options->num_round = NUM_ROUNDS;
test_options->private = 0;
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, NULL);
if (opt == -1)
break;
switch (opt) {
case 'c':
test_options->num_cpu = atoi(optarg);
break;
case 'r':
test_options->num_round = atol(optarg);
break;
case 'p':
test_options->private = atoi(optarg);
break;
case 'h':
default:
print_usage();
ret = -1;
break;
}
}
if (test_options->num_round < 1) {
ODPH_ERR("Invalid number of test rounds: %" PRIu32 "\n", test_options->num_round);
return -1;
}
return ret;
}
static int set_num_cpu(test_global_t *global)
{
int ret, max_num;
test_options_t *test_options = &global->test_options;
int num_cpu = test_options->num_cpu;
return -1;
}
max_num = num_cpu;
if (num_cpu == 0) {
if (max_num > DEFAULT_MAX_WORKERS)
max_num = DEFAULT_MAX_WORKERS;
}
if (num_cpu && ret != num_cpu) {
ODPH_ERR("Too many workers. Max supported %i.\n", ret);
return -1;
}
if (num_cpu == 0) {
if (ret > max_num) {
ODPH_ERR("Too many cpus from odp_cpumask_default_worker(): %i\n", ret);
return -1;
}
num_cpu = ret;
test_options->num_cpu = num_cpu;
}
return 0;
}
static int init_test(test_global_t *global, const char *name, op_bit_t type)
{
init_val.
u64[0] = INIT_VAL;
init_val.
u64[1] = INIT_VAL;
printf("TEST: %s\n", name);
if (type == OP_32BIT)
else if (type == OP_64BIT)
else if (type == OP_128BIT)
else
return -1;
if (type == OP_32BIT) {
global->output[i].u32 = 0;
} else if (type == OP_64BIT) {
global->output[i].u64 = 0;
} else {
global->output[i].u128.u64[0] = 0;
global->output[i].u128.u64[1] = 0;
}
}
return 0;
}
static int run_test(void *arg)
{
uint64_t nsec;
uint64_t cycles;
uint64_t c1, c2;
test_thread_ctx_t *thread_ctx = arg;
test_global_t *global = thread_ctx->global;
test_options_t *test_options = &global->test_options;
uint32_t num_round = test_options->num_round;
uint32_t idx = thread_ctx->idx;
test_fn_t test_func = thread_ctx->func;
op_bit_t type = thread_ctx->type;
void *val;
void *out;
uint32_t out_u32 = 0;
uint64_t out_u64 = 0;
if (type == OP_32BIT) {
val = &global->atomic_u32;
out = &out_u32;
} else if (type == OP_64BIT) {
val = &global->atomic_u64;
out = &out_u64;
} else {
val = &global->atomic_u128;
out = &out_u128;
}
if (global->test_options.private) {
if (type == OP_32BIT)
val = &global->atomic_private[idx].
u32;
else if (type == OP_64BIT)
val = &global->atomic_private[idx].u64;
else
val = &global->atomic_private[idx].u128;
}
test_func(val, out, num_round);
thread_ctx->nsec = nsec;
thread_ctx->cycles = cycles;
if (type == OP_32BIT)
global->output[idx].u32 = out_u32;
else if (type == OP_64BIT)
global->output[idx].u64 = out_u64;
else
global->output[idx].u128 = out_u128;
return 0;
}
static int start_workers(test_global_t *global,
odp_instance_t instance,
test_fn_t func, op_bit_t type)
{
odph_thread_common_param_t param;
int i, ret;
test_options_t *test_options = &global->test_options;
int num_cpu = test_options->num_cpu;
odph_thread_param_t thr_param[num_cpu];
odph_thread_common_param_init(¶m);
param.instance = instance;
param.cpumask = &global->cpumask;
for (i = 0; i < num_cpu; i++) {
test_thread_ctx_t *thread_ctx = &global->thread_ctx[i];
thread_ctx->global = global;
thread_ctx->idx = i;
thread_ctx->func = func;
thread_ctx->type = type;
odph_thread_param_init(&thr_param[i]);
thr_param[i].start = run_test;
thr_param[i].arg = thread_ctx;
}
ret = odph_thread_create(global->thread_tbl, ¶m, thr_param, num_cpu);
if (ret != num_cpu) {
ODPH_ERR("Failed to create all threads %i\n", ret);
return -1;
}
return 0;
}
static int validate_results(test_global_t *global, validate_fn_t validate, op_bit_t type)
{
int i;
test_options_t *test_options = &global->test_options;
uint32_t num_round = test_options->num_round;
int num_cpu = test_options->num_cpu;
int private = global->test_options.private;
void *val;
void *out;
for (i = 0; i < num_cpu; i++) {
if (type == OP_32BIT) {
out = &global->output[i].u32;
val = &global->atomic_u32;
if (private)
val = &global->atomic_private[i].u32;
} else if (type == OP_64BIT) {
out = &global->output[i].u64;
val = &global->atomic_u64;
if (private)
val = &global->atomic_private[i].u64;
} else {
out = &global->output[i].u128;
val = &global->atomic_u128;
if (private)
val = &global->atomic_private[i].u128;
}
if (validate != NULL && validate(val, out, num_round, num_cpu, private))
return -1;
}
return 0;
}
static test_case_t test_suite[] = {
TEST_INFO("odp_atomic_load_u32", test_atomic_load_u32,
validate_atomic_init_val_u32, OP_32BIT),
TEST_INFO("odp_atomic_store_u32", test_atomic_store_u32,
validate_atomic_num_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_fetch_add_u32", test_atomic_fetch_add_u32,
validate_atomic_add_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_add_u32", test_atomic_add_u32,
validate_atomic_add_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_fetch_sub_u32", test_atomic_fetch_sub_u32,
validate_atomic_sub_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_sub_u32", test_atomic_sub_u32,
validate_atomic_sub_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_fetch_inc_u32", test_atomic_fetch_inc_u32,
validate_atomic_add_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_inc_u32", test_atomic_inc_u32,
validate_atomic_add_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_fetch_dec_u32", test_atomic_fetch_dec_u32,
validate_atomic_sub_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_dec_u32", test_atomic_dec_u32,
validate_atomic_sub_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_max_u32", test_atomic_max_u32,
validate_atomic_max_u32, OP_32BIT),
TEST_INFO("odp_atomic_fetch_max_u32", test_atomic_fetch_max_u32,
validate_atomic_fetch_max_u32, OP_32BIT),
TEST_INFO("odp_atomic_min_u32", test_atomic_min_u32,
validate_atomic_min_u32, OP_32BIT),
TEST_INFO("odp_atomic_fetch_min_u32", test_atomic_fetch_min_u32,
validate_atomic_fetch_min_u32, OP_32BIT),
TEST_INFO("odp_atomic_cas_u32", test_atomic_cas_u32,
validate_atomic_cas_u32, OP_32BIT),
TEST_INFO("odp_atomic_xchg_u32", test_atomic_xchg_u32,
validate_atomic_num_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_bit_set_u32", test_atomic_bit_set_u32,
NULL, OP_32BIT),
TEST_INFO("odp_atomic_bit_fetch_set_u32", test_atomic_bit_fetch_set_u32,
NULL, OP_32BIT),
TEST_INFO("odp_atomic_bit_clr_u32", test_atomic_bit_clr_u32,
NULL, OP_32BIT),
TEST_INFO("odp_atomic_bit_fetch_clr_u32", test_atomic_bit_fetch_clr_u32,
NULL, OP_32BIT),
TEST_INFO("odp_atomic_load_acq_u32", test_atomic_load_acq_u32,
validate_atomic_init_val_u32, OP_32BIT),
TEST_INFO("odp_atomic_store_rel_u32", test_atomic_store_rel_u32,
validate_atomic_num_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_add_rel_u32", test_atomic_add_rel_u32,
validate_atomic_add_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_sub_rel_u32", test_atomic_sub_rel_u32,
validate_atomic_sub_round_u32, OP_32BIT),
TEST_INFO("odp_atomic_cas_acq_u32", test_atomic_cas_acq_u32,
validate_atomic_cas_u32, OP_32BIT),
TEST_INFO("odp_atomic_cas_rel_u32", test_atomic_cas_rel_u32,
validate_atomic_cas_u32, OP_32BIT),
TEST_INFO("odp_atomic_cas_acq_rel_u32", test_atomic_cas_acq_rel_u32,
validate_atomic_cas_u32, OP_32BIT),
TEST_INFO("odp_atomic_bit_set_rel_u32", test_atomic_bit_set_rel_u32,
NULL, OP_32BIT),
TEST_INFO("odp_atomic_bit_clr_rel_u32", test_atomic_bit_clr_rel_u32,
NULL, OP_32BIT),
TEST_INFO("odp_atomic_load_u64", test_atomic_load_u64,
validate_atomic_init_val_u64, OP_64BIT),
TEST_INFO("odp_atomic_store_u64", test_atomic_store_u64,
validate_atomic_num_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_fetch_add_u64", test_atomic_fetch_add_u64,
validate_atomic_add_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_add_u64", test_atomic_add_u64,
validate_atomic_add_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_fetch_sub_u64", test_atomic_fetch_sub_u64,
validate_atomic_sub_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_sub_u64", test_atomic_sub_u64,
validate_atomic_sub_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_fetch_inc_u64", test_atomic_fetch_inc_u64,
validate_atomic_add_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_inc_u64", test_atomic_inc_u64,
validate_atomic_add_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_fetch_dec_u64", test_atomic_fetch_dec_u64,
validate_atomic_sub_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_dec_u64", test_atomic_dec_u64,
validate_atomic_sub_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_max_u64", test_atomic_max_u64,
validate_atomic_max_u64, OP_64BIT),
TEST_INFO("odp_atomic_fetch_max_u64", test_atomic_fetch_max_u64,
validate_atomic_fetch_max_u64, OP_64BIT),
TEST_INFO("odp_atomic_min_u64", test_atomic_min_u64,
validate_atomic_min_u64, OP_64BIT),
TEST_INFO("odp_atomic_fetch_min_u64", test_atomic_fetch_min_u64,
validate_atomic_fetch_min_u64, OP_64BIT),
TEST_INFO("odp_atomic_cas_u64", test_atomic_cas_u64,
validate_atomic_cas_u64, OP_64BIT),
TEST_INFO("odp_atomic_xchg_u64", test_atomic_xchg_u64,
validate_atomic_num_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_bit_set_u64", test_atomic_bit_set_u64,
NULL, OP_64BIT),
TEST_INFO("odp_atomic_bit_fetch_set_u64", test_atomic_bit_fetch_set_u64,
NULL, OP_64BIT),
TEST_INFO("odp_atomic_bit_clr_u64", test_atomic_bit_clr_u64,
NULL, OP_64BIT),
TEST_INFO("odp_atomic_bit_fetch_clr_u64", test_atomic_bit_fetch_clr_u64,
NULL, OP_64BIT),
TEST_INFO("odp_atomic_load_acq_u64", test_atomic_load_acq_u64,
validate_atomic_init_val_u64, OP_64BIT),
TEST_INFO("odp_atomic_store_rel_u64", test_atomic_store_rel_u64,
validate_atomic_num_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_add_rel_u64", test_atomic_add_rel_u64,
validate_atomic_add_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_sub_rel_u64", test_atomic_sub_rel_u64,
validate_atomic_sub_round_u64, OP_64BIT),
TEST_INFO("odp_atomic_cas_acq_u64", test_atomic_cas_acq_u64,
validate_atomic_cas_u64, OP_64BIT),
TEST_INFO("odp_atomic_cas_rel_u64", test_atomic_cas_rel_u64,
validate_atomic_cas_u64, OP_64BIT),
TEST_INFO("odp_atomic_cas_acq_rel_u64", test_atomic_cas_acq_rel_u64,
validate_atomic_cas_u64, OP_64BIT),
TEST_INFO("odp_atomic_bit_set_rel_u64", test_atomic_bit_set_rel_u64,
NULL, OP_64BIT),
TEST_INFO("odp_atomic_bit_clr_rel_u64", test_atomic_bit_clr_rel_u64,
NULL, OP_64BIT),
TEST_INFO("odp_atomic_load_u128", test_atomic_load_u128,
validate_atomic_init_val_u128, OP_128BIT),
TEST_INFO("odp_atomic_store_u128", test_atomic_store_u128,
validate_atomic_num_round_u128, OP_128BIT),
TEST_INFO("odp_atomic_cas_u128", test_atomic_cas_u128,
validate_atomic_cas_u128, OP_128BIT),
TEST_INFO("odp_atomic_cas_acq_u128", test_atomic_cas_acq_u128,
validate_atomic_cas_u128, OP_128BIT),
TEST_INFO("odp_atomic_cas_rel_u128", test_atomic_cas_rel_u128,
validate_atomic_cas_u128, OP_128BIT),
TEST_INFO("odp_atomic_cas_acq_rel_u128", test_atomic_cas_acq_rel_u128,
validate_atomic_cas_u128, OP_128BIT),
};
"Result array is too small to hold all the results");
static void output_results(test_global_t *global, int idx)
{
int i, num;
double nsec_ave, nsec_per_op, cycles_per_op, operations_per_cpu, total_operations;
test_options_t *test_options = &global->test_options;
int num_cpu = test_options->num_cpu;
uint32_t num_round = test_options->num_round;
uint64_t nsec_sum = 0;
uint64_t cycles_sum = 0;
global->results[idx].test_name = test_suite[idx].name;
nsec_sum += global->thread_ctx[i].nsec;
cycles_sum += global->thread_ctx[i].cycles;
}
if (nsec_sum == 0 || cycles_sum == 0) {
printf("No results.\n");
return;
}
nsec_ave = (double)nsec_sum / num_cpu;
nsec_per_op = (double)nsec_sum / (num_cpu * num_round);
cycles_per_op = (double)cycles_sum / (num_cpu * num_round);
num = 0;
operations_per_cpu = num_round / (nsec_ave / 1000.0);
total_operations = (num_cpu * num_round) / (nsec_ave / 1000.0);
global->results[idx].cycles_per_op = cycles_per_op;
global->results[idx].operations_per_cpu = operations_per_cpu;
global->results[idx].nsec_per_op = nsec_per_op;
global->results[idx].total_operations = total_operations;
printf("---------------------------------------------\n");
printf("Per thread results (Millions of ops per sec):\n");
printf("---------------------------------------------\n");
printf(" 1 2 3 4 5 6 7 8 9 10");
if (global->thread_ctx[i].nsec) {
if ((num % 10) == 0)
printf("\n ");
printf("%8.2f ", num_round / (global->thread_ctx[i].nsec / 1000.0));
num++;
}
}
printf("\n\n");
printf("Average results over %i threads:\n", num_cpu);
printf("---------------------------------------\n");
printf(" cycles per op: %8.2f\n", cycles_per_op);
printf(" nsec per op: %8.2f\n", nsec_per_op);
printf(" ops per cpu: %8.2fM ops/sec\n", operations_per_cpu);
printf(" total ops: %8.2fM ops/sec\n", total_operations);
printf("\n\n");
}
int main(int argc, char **argv)
{
odph_helper_options_t helper_options;
test_options_t test_options;
int num_tests, i;
test_common_options_t common_options;
argc = odph_parse_options(argc, argv);
if (odph_options(&helper_options)) {
ODPH_ERR("Error: reading ODP helper options failed.\n");
exit(EXIT_FAILURE);
}
argc = test_common_parse_options(argc, argv);
if (test_common_options(&common_options)) {
ODPH_ERR("Error while reading test options, exiting\n");
exit(EXIT_FAILURE);
}
if (parse_options(argc, argv, &test_options))
exit(EXIT_FAILURE);
ODPH_ERR("Global init failed.\n");
exit(EXIT_FAILURE);
}
ODPH_ERR("Local init failed.\n");
exit(EXIT_FAILURE);
}
ODP_CACHE_LINE_SIZE, 0);
ODPH_ERR("Shared memory reserve failed.\n");
exit(EXIT_FAILURE);
}
if (test_global == NULL) {
ODPH_ERR("Shared memory alloc failed.\n");
exit(EXIT_FAILURE);
}
memset(test_global, 0, sizeof(test_global_t));
test_global->test_options = test_options;
test_global->common_options = common_options;
if (set_num_cpu(test_global))
exit(EXIT_FAILURE);
print_info(&test_global->test_options);
num_tests = ODPH_ARRAY_SIZE(test_suite);
for (i = 0; i < num_tests; i++) {
if (init_test(test_global, test_suite[i].name, test_suite[i].type)) {
ODPH_ERR("Failed to initialize atomics.\n");
exit(EXIT_FAILURE);
}
if (start_workers(test_global, instance, test_suite[i].test_fn, test_suite[i].type))
exit(EXIT_FAILURE);
odph_thread_join(test_global->thread_tbl, test_global->test_options.num_cpu);
output_results(test_global, i);
if (validate_results(test_global, test_suite[i].validate_fn, test_suite[i].type)) {
ODPH_ERR("Test %s result validation failed.\n", test_suite[i].name);
exit(EXIT_FAILURE);
}
}
if (output_summary(test_global)) {
ODPH_ERR("Outputting summary failed.\n");
exit(EXIT_FAILURE);
}
ODPH_ERR("Shm free failed.\n");
exit(EXIT_FAILURE);
}
ODPH_ERR("Local terminate failed.\n");
exit(EXIT_FAILURE);
}
ODPH_ERR("Global terminate failed.\n");
exit(EXIT_FAILURE);
}
return 0;
}
void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val)
Initialize atomic uint32 variable.
void odp_atomic_store_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
Store value to atomic uint64 variable using RELEASE memory ordering.
int odp_atomic_cas_rel_u64(odp_atomic_u64_t *atom, uint64_t *old_val, uint64_t new_val)
Compare and swap atomic uint64 variable using RELEASE memory ordering.
uint32_t odp_atomic_fetch_max_u32(odp_atomic_u32_t *atom, uint32_t new_max)
Fetch and update maximum value of atomic uint32 variable.
void odp_atomic_max_u64(odp_atomic_u64_t *atom, uint64_t new_max)
Update maximum value of atomic uint64 variable.
void odp_atomic_bit_set_u32(odp_atomic_u32_t *atom, uint32_t bits)
Set bits in atomic uint32 variable.
int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom, uint32_t *old_val, uint32_t new_val)
Compare and swap atomic uint32 variable using ACQUIRE memory ordering.
int odp_atomic_cas_acq_rel_u64(odp_atomic_u64_t *atom, uint64_t *old_val, uint64_t new_val)
Compare and swap atomic uint64 variable using ACQUIRE-and-RELEASE memory ordering.
void odp_atomic_add_u32(odp_atomic_u32_t *atom, uint32_t val)
Add to atomic uint32 variable.
uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom)
Load value of atomic uint32 variable.
void odp_atomic_inc_u32(odp_atomic_u32_t *atom)
Increment atomic uint32 variable.
void odp_atomic_dec_u64(odp_atomic_u64_t *atom)
Decrement atomic uint64 variable.
void odp_atomic_bit_set_u64(odp_atomic_u64_t *atom, uint64_t bits)
Set bits in atomic uint64 variable.
void odp_atomic_bit_clr_rel_u64(odp_atomic_u64_t *atom, uint64_t bits)
Clear bits in atomic uint64 variable using RELEASE memory ordering.
void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val)
Initialize atomic uint64 variable.
void odp_atomic_max_u32(odp_atomic_u32_t *atom, uint32_t new_max)
Update maximum value of atomic uint32 variable.
uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, uint32_t val)
Fetch and subtract from atomic uint32 variable.
uint64_t odp_atomic_fetch_max_u64(odp_atomic_u64_t *atom, uint64_t new_max)
Fetch and update maximum value of atomic uint64 variable.
int odp_atomic_cas_acq_rel_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val, odp_u128_t new_val)
Compare and swap atomic odp_u128_t variable using ACQUIRE-and-RELEASE memory ordering.
uint64_t odp_atomic_load_acq_u64(odp_atomic_u64_t *atom)
Load value of atomic uint64 variable using ACQUIRE memory ordering.
uint64_t odp_atomic_xchg_u64(odp_atomic_u64_t *atom, uint64_t new_val)
Exchange value of atomic uint64 variable.
int odp_atomic_lock_free_u64(odp_atomic_op_t *atomic_op)
Query which atomic uint64 operations are lock-free.
uint64_t odp_atomic_fetch_min_u64(odp_atomic_u64_t *atom, uint64_t new_min)
Fetch and update minimum value of atomic uint64_t variable.
uint32_t odp_atomic_fetch_min_u32(odp_atomic_u32_t *atom, uint32_t new_min)
Fetch and update minimum value of atomic uint32 variable.
void odp_atomic_dec_u32(odp_atomic_u32_t *atom)
Decrement atomic uint32 variable.
void odp_atomic_min_u32(odp_atomic_u32_t *atom, uint32_t new_min)
Update minimum value of atomic uint32 variable.
uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom)
Fetch and increment atomic uint32 variable.
uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, uint32_t val)
Fetch and add to atomic uint32 variable.
uint64_t odp_atomic_bit_fetch_clr_u64(odp_atomic_u64_t *atom, uint64_t bits)
Fetch value and clear bits in atomic uint64 variable.
uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom)
Load value of atomic uint32 variable using ACQUIRE memory ordering.
uint32_t odp_atomic_bit_fetch_set_u32(odp_atomic_u32_t *atom, uint32_t bits)
Fetch value and set bits in atomic uint32 variable.
void odp_atomic_bit_set_rel_u64(odp_atomic_u64_t *atom, uint64_t bits)
Set bits in atomic uint64 variable using RELEASE memory ordering.
uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom)
Fetch and decrement atomic uint64 variable.
int odp_atomic_cas_u32(odp_atomic_u32_t *atom, uint32_t *old_val, uint32_t new_val)
Compare and swap atomic uint32 variable.
void odp_atomic_add_rel_u32(odp_atomic_u32_t *atom, uint32_t val)
Add to atomic uint32 variable using RELEASE memory ordering.
int odp_atomic_cas_rel_u32(odp_atomic_u32_t *atom, uint32_t *old_val, uint32_t new_val)
Compare and swap atomic uint32 variable using RELEASE memory ordering.
void odp_atomic_bit_set_rel_u32(odp_atomic_u32_t *atom, uint32_t bits)
Set bits in atomic uint32 variable using RELEASE memory ordering.
void odp_atomic_bit_clr_u32(odp_atomic_u32_t *atom, uint32_t bits)
Clear bits in atomic uint32 variable.
int odp_atomic_cas_acq_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val, odp_u128_t new_val)
Compare and swap atomic odp_u128_t variable using ACQUIRE memory ordering.
void odp_atomic_inc_u64(odp_atomic_u64_t *atom)
Increment atomic uint64 variable.
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, uint64_t val)
Fetch and subtract from atomic uint64 variable.
int odp_atomic_cas_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val, odp_u128_t new_val)
Compare and swap atomic odp_u128_t variable.
int odp_atomic_cas_rel_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val, odp_u128_t new_val)
Compare and swap atomic odp_u128_t variable using RELEASE memory ordering.
int odp_atomic_lock_free_u128(odp_atomic_op_t *atomic_op)
Query which atomic odp_atomic_u128_t operations are lock-free.
void odp_atomic_sub_rel_u32(odp_atomic_u32_t *atom, uint32_t val)
Subtract from atomic uint32 variable using RELEASE memory ordering.
uint32_t odp_atomic_bit_fetch_clr_u32(odp_atomic_u32_t *atom, uint32_t bits)
Fetch value and clear bits in atomic uint32 variable.
void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val)
Subtract from atomic uint64 variable.
odp_u128_t odp_atomic_load_u128(odp_atomic_u128_t *atom)
Load value of atomic odp_u128_t variable.
uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom)
Fetch and decrement atomic uint32 variable.
void odp_atomic_store_u64(odp_atomic_u64_t *atom, uint64_t val)
Store value to atomic uint64 variable.
void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val)
Add to atomic uint64 variable.
int odp_atomic_cas_acq_rel_u32(odp_atomic_u32_t *atom, uint32_t *old_val, uint32_t new_val)
Compare and swap atomic uint32 variable using ACQUIRE-and-RELEASE memory ordering.
int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val, uint64_t new_val)
Compare and swap atomic uint64 variable.
void odp_atomic_add_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
Add to atomic uint64 variable using RELEASE memory ordering.
uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom)
Fetch and increment atomic uint64 variable.
uint32_t odp_atomic_xchg_u32(odp_atomic_u32_t *atom, uint32_t new_val)
Exchange value of atomic uint32 variable.
uint64_t odp_atomic_bit_fetch_set_u64(odp_atomic_u64_t *atom, uint64_t bits)
Fetch value and set bits in atomic uint64 variable.
void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min)
Update minimum value of atomic uint64 variable.
void odp_atomic_sub_u32(odp_atomic_u32_t *atom, uint32_t val)
Subtract from atomic uint32 variable.
int odp_atomic_cas_acq_u64(odp_atomic_u64_t *atom, uint64_t *old_val, uint64_t new_val)
Compare and swap atomic uint64 variable using ACQUIRE memory ordering.
void odp_atomic_init_u128(odp_atomic_u128_t *atom, odp_u128_t val)
Initialize atomic odp_u128_t variable.
void odp_atomic_sub_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
Subtract from atomic uint64 variable using RELEASE memory ordering.
void odp_atomic_store_u128(odp_atomic_u128_t *atom, odp_u128_t val)
Store value to atomic odp_u128_t variable.
void odp_atomic_bit_clr_u64(odp_atomic_u64_t *atom, uint64_t bits)
Clear bits in atomic uint64 variable.
void odp_atomic_bit_clr_rel_u32(odp_atomic_u32_t *atom, uint32_t bits)
Clear bits in atomic uint32 variable using RELEASE memory ordering.
uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, uint64_t val)
Fetch and add to atomic uint64 variable.
uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom)
Load value of atomic uint64 variable.
void odp_atomic_store_rel_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable using RELEASE memory ordering.
void odp_barrier_init(odp_barrier_t *barr, int count)
Initialize barrier with thread count.
void odp_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
#define ODP_ALIGNED_CACHE
Defines type/struct/variable to be cache line size aligned.
#define ODP_UNUSED
Intentionally unused variables of functions.
uint64_t odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
CPU cycle count difference.
uint64_t odp_cpu_cycles(void)
Current CPU cycle count.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
#define ODP_STATIC_ASSERT(cond, msg)
Compile time assertion macro.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_INVALID
Invalid shared memory block.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
void odp_sys_info_print(void)
Print system info.
#define ODP_THREAD_COUNT_MAX
Maximum number of threads supported in build time.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
odp_time_t odp_time_local_strict(void)
Current local time (strict)
uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
Time difference in nanoseconds.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
odp_feature_t not_used
Unused features.
128-bit unsigned integer structure
uint32_t u32[4]
128 bits as uint32_t words
uint64_t u64[2]
128 bits as uint64_t words
uint32_t fetch_max
Atomic fetch and maximum.
uint32_t bit_clr
Atomic bit clear.
uint32_t fetch_add
Atomic fetch and add.
uint32_t fetch_sub
Atomic fetch and subtract.
uint32_t xchg
Atomic exchange.
uint32_t bit_set
Atomic bit set.
struct odp_atomic_op_t::@6 op
Operation flags.
uint32_t sub
Atomic subtract.
uint32_t load
Atomic load.
uint32_t fetch_dec
Atomic fetch and decrement.
uint32_t fetch_inc
Atomic fetch and increment.
uint32_t inc
Atomic increment.
uint32_t bit_fetch_set
Atomic bit fetch and set.
uint32_t min
Atomic minimum.
uint32_t max
Atomic maximum.
uint32_t all_bits
All bits of the bit field structure.
uint32_t cas
Atomic compare and swap.
uint32_t store
Atomic store.
uint32_t fetch_min
Atomic fetch and minimum.
uint32_t dec
Atomic decrement.
uint32_t bit_fetch_clr
Atomic bit fetch and clear.
uint32_t tm
Traffic Manager APIs, e.g., odp_tm_xxx()
uint32_t stash
Stash APIs, e.g., odp_stash_xxx()
uint32_t crypto
Crypto APIs, e.g., odp_crypto_xxx()
uint32_t ipsec
IPsec APIs, e.g., odp_ipsec_xxx()
uint32_t timer
Timer APIs, e.g., odp_timer_xxx(), odp_timeout_xxx()
uint32_t cls
Classifier APIs, e.g., odp_cls_xxx(), odp_cos_xxx()
uint32_t schedule
Scheduler APIs, e.g., odp_schedule_xxx()
struct odp_feature_t::@148 feat
Individual feature bits.
uint32_t compress
Compression APIs, e.g., odp_comp_xxx()