aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Khoronzhuk <ivan.khoronzhuk@linaro.org>2016-01-15 17:03:56 +0200
committerIvan Khoronzhuk <ivan.khoronzhuk@linaro.org>2016-01-15 17:03:56 +0200
commit41a0e90cf821254be7cf0d528b5c86cc08d22999 (patch)
tree58c1b714a1400401728359d05352864ecd8c4405
parent3208b66cfeb195d184ab9756d2ca5bb1fb58f76d (diff)
parent3b7f7085fd128c0e32756b1d35b898c8aa5a74c0 (diff)
Merge remote-tracking branch 'linaro-odp/master' into new_master
-rw-r--r--DEPENDENCIES7
-rw-r--r--configure.ac4
-rw-r--r--doc/Makefile.am7
-rw-r--r--doc/application-api-guide/Makefile.am5
-rw-r--r--doc/application-api-guide/api_guide_lines.dox (renamed from doc/api_guide_lines.dox)0
-rw-r--r--doc/application-api-guide/doxygen.cfg (renamed from doc/doxygen.cfg)0
-rw-r--r--doc/application-api-guide/examples.dox (renamed from doc/examples.dox)0
-rw-r--r--doc/application-api-guide/odp.dox (renamed from doc/odp.dox)0
-rw-r--r--doc/application-api-guide/release.dox (renamed from doc/release.dox)0
-rw-r--r--example/Makefile.am2
-rw-r--r--example/classifier/odp_classifier.c3
-rw-r--r--example/time/.gitignore1
-rw-r--r--example/time/Makefile.am10
-rw-r--r--example/time/time_global_test.c358
-rwxr-xr-xtest/performance/odp_l2fwd_run13
15 files changed, 390 insertions, 20 deletions
diff --git a/DEPENDENCIES b/DEPENDENCIES
index fec65d2b..3563b36b 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -215,8 +215,5 @@ The tested version of doxygen is 1.8.8
5.2 User guides
5.2.1 HTML
- # Ubuntu
- $ apt-get install asciidoc source-highlight
-
- # Debian
- $ apt-get install asciidoc source-highlight
+ # Debian/Ubuntu
+ $ apt-get install asciidoc source-highlight librsvg2-bin
diff --git a/configure.ac b/configure.ac
index 1e8313ca..a82e1f62 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,8 +136,7 @@ AC_ARG_ENABLE([cunit_support],
##########################################################################
DX_HTML_FEATURE(ON)
DX_PDF_FEATURE(ON)
-DX_INIT_DOXYGEN($PACKAGE_NAME, doc/doxygen.cfg, doc/output)
-
+DX_INIT_DOXYGEN($PACKAGE_NAME, doc/application-api-guide/doxygen.cfg, doc/output)
##########################################################################
# Enable/disable Unit tests
##########################################################################
@@ -333,6 +332,7 @@ AC_CONFIG_FILES([Makefile
example/generator/Makefile
example/ipsec/Makefile
example/packet/Makefile
+ example/time/Makefile
example/timer/Makefile
helper/Makefile
helper/test/Makefile
diff --git a/doc/Makefile.am b/doc/Makefile.am
index a1e99036..41d804bc 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -8,10 +8,3 @@ endif
if user_guide
SUBDIRS += implementers-guide users-guide process-guide
endif
-
-EXTRA_DIST = \
- api_guide_lines.dox \
- examples.dox \
- images \
- odp.dox \
- release.dox
diff --git a/doc/application-api-guide/Makefile.am b/doc/application-api-guide/Makefile.am
new file mode 100644
index 00000000..10f6030f
--- /dev/null
+++ b/doc/application-api-guide/Makefile.am
@@ -0,0 +1,5 @@
+EXTRA_DIST = \
+ api_guide_lines.dox \
+ examples.dox \
+ odp.dox \
+ release.dox
diff --git a/doc/api_guide_lines.dox b/doc/application-api-guide/api_guide_lines.dox
index c544afd6..c544afd6 100644
--- a/doc/api_guide_lines.dox
+++ b/doc/application-api-guide/api_guide_lines.dox
diff --git a/doc/doxygen.cfg b/doc/application-api-guide/doxygen.cfg
index 909f0ce4..909f0ce4 100644
--- a/doc/doxygen.cfg
+++ b/doc/application-api-guide/doxygen.cfg
diff --git a/doc/examples.dox b/doc/application-api-guide/examples.dox
index 2dccd7f8..2dccd7f8 100644
--- a/doc/examples.dox
+++ b/doc/application-api-guide/examples.dox
diff --git a/doc/odp.dox b/doc/application-api-guide/odp.dox
index 0bff5ad9..0bff5ad9 100644
--- a/doc/odp.dox
+++ b/doc/application-api-guide/odp.dox
diff --git a/doc/release.dox b/doc/application-api-guide/release.dox
index eb6eca73..eb6eca73 100644
--- a/doc/release.dox
+++ b/doc/application-api-guide/release.dox
diff --git a/example/Makefile.am b/example/Makefile.am
index 353f397f..39d9b019 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -1 +1 @@
-SUBDIRS = classifier generator ipsec packet timer
+SUBDIRS = classifier generator ipsec packet time timer
diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
index fe1c3b6e..6b443d73 100644
--- a/example/classifier/odp_classifier.c
+++ b/example/classifier/odp_classifier.c
@@ -167,7 +167,8 @@ int parse_ipv4_addr(const char *ipaddress, uint64_t *addr)
uint32_t b[4];
int converted;
- converted = sscanf(ipaddress, "%d.%d.%d.%d",
+ converted = sscanf(ipaddress,
+ "%" SCNu32 ".%" SCNu32 ".%" SCNu32 ".%" SCNu32 "",
&b[3], &b[2], &b[1], &b[0]);
if (4 != converted)
return -1;
diff --git a/example/time/.gitignore b/example/time/.gitignore
new file mode 100644
index 00000000..3106aea9
--- /dev/null
+++ b/example/time/.gitignore
@@ -0,0 +1 @@
+odp_time_global_test
diff --git a/example/time/Makefile.am b/example/time/Makefile.am
new file mode 100644
index 00000000..915593a3
--- /dev/null
+++ b/example/time/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/example/Makefile.inc
+
+bin_PROGRAMS = odp_time_global_test$(EXEEXT)
+odp_time_global_test_LDFLAGS = $(AM_LDFLAGS) -static
+odp_time_global_test_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+
+noinst_HEADERS = \
+ $(top_srcdir)/example/example_debug.h
+
+dist_odp_time_global_test_SOURCES = time_global_test.c
diff --git a/example/time/time_global_test.c b/example/time/time_global_test.c
new file mode 100644
index 00000000..df0826c5
--- /dev/null
+++ b/example/time/time_global_test.c
@@ -0,0 +1,358 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp.h>
+#include <example_debug.h>
+#include <odp/helper/linux.h>
+
+#define MAX_WORKERS 32
+#define ITERATION_NUM 2048
+#define LOG_BASE 8
+#define LOG_ENTRY_SIZE 19
+#define LOG_LINE_SIZE (LOG_BASE * LOG_ENTRY_SIZE + 1)
+
+#define QUEUE_NAME_PREFIX "thread_queue_"
+
+typedef struct {
+ odp_time_t timestamp;
+ int id;
+} timestamp_event_t;
+
+typedef struct {
+ uint8_t thr;
+ uint8_t id;
+ odp_time_t time;
+} log_entry_t;
+
+typedef struct {
+ uint32_t iteration_num;
+ odp_atomic_u32_t iteration_counter;
+ odp_atomic_u32_t id_counter;
+ odp_atomic_u32_t log_counter;
+ odp_atomic_u32_t err_counter;
+ odp_barrier_t start_barrier;
+ odp_barrier_t end_barrier;
+ int thread_num;
+ log_entry_t *log;
+ int log_enries_num;
+} test_globals_t;
+
+static void print_log(test_globals_t *gbls)
+{
+ uint32_t err_num;
+ int i, j, k, pad;
+ char line[LOG_LINE_SIZE];
+
+ memset(line, '-', LOG_LINE_SIZE - 1);
+ line[LOG_LINE_SIZE - 1] = 0;
+ for (i = 1; i <= gbls->thread_num; i++) {
+ printf("\n==== history of %d buffer, time,ns (thread) ====\n%s\n",
+ i, line);
+
+ /* print log for buffer */
+ k = 0;
+ for (j = 0; j < gbls->log_enries_num; j++)
+ if (gbls->log[j].id == i) {
+ printf("%10" PRIu64 " (%-3d)",
+ odp_time_to_ns(gbls->log[j].time),
+ gbls->log[j].thr);
+
+ if (!(++k % LOG_BASE))
+ printf(" |\n");
+ else
+ printf(" =>");
+ }
+
+ if ((k % LOG_BASE)) {
+ pad = (LOG_BASE - k % LOG_BASE) * LOG_ENTRY_SIZE - 4;
+ printf(" end%*c\n%s\n", pad, '|', line);
+ } else {
+ printf("%s\n", line);
+ }
+ }
+
+ printf("\n\n");
+
+ err_num = odp_atomic_load_u32(&gbls->err_counter);
+ if (err_num)
+ printf("Number of errors: %u\n", err_num);
+}
+
+static void
+generate_next_queue(test_globals_t *gbls, odp_queue_t *queue, unsigned int id)
+{
+ int thr;
+ unsigned int rand_id;
+ char queue_name[sizeof(QUEUE_NAME_PREFIX) + 2];
+
+ thr = odp_thread_id();
+
+ /* generate next random id */
+ do {
+ odp_random_data((uint8_t *)&rand_id, sizeof(rand_id), 1);
+ rand_id = rand_id % gbls->thread_num + 1;
+ } while (rand_id == id);
+
+ sprintf(queue_name, QUEUE_NAME_PREFIX "%d", rand_id);
+ *queue = odp_queue_lookup(queue_name);
+
+ if (ODP_QUEUE_INVALID == *queue)
+ EXAMPLE_ABORT("Cannot lookup thread queue \"%s\", thread %d\n",
+ queue_name, thr);
+}
+
+static void test_global_timestamps(test_globals_t *gbls,
+ odp_queue_t queue, unsigned int id)
+{
+ int thr;
+ int log_entry;
+ odp_event_t ev;
+ odp_time_t time;
+ odp_buffer_t buf;
+ odp_queue_t queue_next;
+ timestamp_event_t *timestamp_ev;
+
+ thr = odp_thread_id();
+ while (odp_atomic_load_u32(&gbls->iteration_counter) <
+ gbls->iteration_num) {
+ ev = odp_queue_deq(queue);
+
+ if (ev == ODP_EVENT_INVALID)
+ continue;
+
+ buf = odp_buffer_from_event(ev);
+ timestamp_ev = (timestamp_event_t *)odp_buffer_addr(buf);
+
+ time = odp_time_global();
+ if (odp_time_cmp(time, timestamp_ev->timestamp) < 0) {
+ EXAMPLE_ERR("timestamp is less than previous time_prev=%"
+ PRIu64 "ns, time_next=%"
+ PRIu64 "ns, thread %d\n",
+ odp_time_to_ns(timestamp_ev->timestamp),
+ odp_time_to_ns(time), thr);
+ odp_atomic_inc_u32(&gbls->err_counter);
+ }
+
+ /* update the log */
+ log_entry = odp_atomic_fetch_inc_u32(&gbls->log_counter);
+ gbls->log[log_entry].time = timestamp_ev->timestamp;
+ gbls->log[log_entry].id = timestamp_ev->id;
+ gbls->log[log_entry].thr = thr;
+
+ /* assign new current time and send */
+ generate_next_queue(gbls, &queue_next, id);
+ timestamp_ev->timestamp = time;
+ if (odp_queue_enq(queue_next, ev))
+ EXAMPLE_ABORT("Cannot enqueue event %"
+ PRIu64 " on queue %"
+ PRIu64 ", thread %d\n",
+ odp_event_to_u64(ev),
+ odp_queue_to_u64(queue_next), thr);
+
+ odp_atomic_inc_u32(&gbls->iteration_counter);
+ }
+}
+
+/**
+ * @internal Worker thread
+ *
+ * @param ptr Pointer to test arguments
+ *
+ * @return Pointer to exit status
+ */
+static void *run_thread(void *ptr)
+{
+ int thr;
+ uint32_t id;
+ odp_event_t ev;
+ odp_buffer_t buf;
+ test_globals_t *gbls;
+ odp_pool_t buffer_pool;
+ odp_queue_param_t qparams;
+ odp_queue_t queue, queue_next;
+ timestamp_event_t *timestamp_ev;
+ char queue_name[sizeof(QUEUE_NAME_PREFIX) + 2];
+
+ gbls = ptr;
+ thr = odp_thread_id();
+ printf("Thread %i starts on cpu %i\n", thr, odp_cpu_id());
+
+ /*
+ * Allocate own queue for receiving timestamps.
+ * Own queue is needed to guarantee that next thread for receiving
+ * buffer is not the same thread.
+ */
+ odp_queue_param_init(&qparams);
+ qparams.sched.prio = ODP_SCHED_PRIO_LOWEST;
+ qparams.sched.sync = ODP_SCHED_SYNC_NONE;
+ qparams.sched.group = ODP_SCHED_GROUP_WORKER;
+
+ id = odp_atomic_fetch_inc_u32(&gbls->id_counter);
+ sprintf(queue_name, QUEUE_NAME_PREFIX "%d", id);
+ queue = odp_queue_create(queue_name, ODP_QUEUE_TYPE_POLL, &qparams);
+ if (queue == ODP_QUEUE_INVALID)
+ EXAMPLE_ABORT("Cannot create thread queue, thread %d", thr);
+
+ /* allocate buffer for timestamp */
+ buffer_pool = odp_pool_lookup("time buffers pool");
+ if (buffer_pool == ODP_POOL_INVALID)
+ EXAMPLE_ABORT("Buffer pool was not found, thread %d\n", thr);
+
+ buf = odp_buffer_alloc(buffer_pool);
+ if (buf == ODP_BUFFER_INVALID)
+ EXAMPLE_ABORT("Buffer was not allocated, thread %d\n", thr);
+
+ /* wait all threads allocated their queues */
+ odp_barrier_wait(&gbls->start_barrier);
+
+ /* enqueue global timestamp to some queue of some other thread */
+ generate_next_queue(gbls, &queue_next, id);
+
+ /* save global timestamp and id for tracing */
+ ev = odp_buffer_to_event(buf);
+ timestamp_ev = (timestamp_event_t *)odp_buffer_addr(buf);
+ timestamp_ev->id = id;
+ timestamp_ev->timestamp = odp_time_global();
+ if (odp_queue_enq(queue_next, ev))
+ EXAMPLE_ABORT("Cannot enqueue timestamp event %"
+ PRIu64 " on queue %" PRIu64 ", thread %d",
+ odp_event_to_u64(ev),
+ odp_queue_to_u64(queue_next), thr);
+
+ test_global_timestamps(gbls, queue, id);
+
+ /* wait all threads are finished their jobs */
+ odp_barrier_wait(&gbls->end_barrier);
+
+ /* free all events on the allocated queue */
+ while (1) {
+ ev = odp_queue_deq(queue);
+ if (ev == ODP_EVENT_INVALID)
+ break;
+
+ buf = odp_buffer_from_event(ev);
+ odp_buffer_free(buf);
+ }
+
+ /* free allocated queue */
+ if (odp_queue_destroy(queue))
+ EXAMPLE_ABORT("Cannot destroy queue %" PRIu64 "",
+ odp_queue_to_u64(queue));
+
+ printf("Thread %i exits\n", thr);
+ fflush(NULL);
+ return NULL;
+}
+
+int main(void)
+{
+ int err = 0;
+ odp_pool_t pool = ODP_POOL_INVALID;
+ int num_workers;
+ test_globals_t *gbls;
+ odp_cpumask_t cpumask;
+ odp_pool_param_t params;
+ odp_shm_t shm_glbls = ODP_SHM_INVALID;
+ odp_shm_t shm_log = ODP_SHM_INVALID;
+ int log_size, log_enries_num;
+ odph_linux_pthread_t thread_tbl[MAX_WORKERS];
+
+ printf("\nODP global time test starts\n");
+
+ if (odp_init_global(NULL, NULL)) {
+ err = 1;
+ EXAMPLE_ERR("ODP global init failed.\n");
+ goto end;
+ }
+
+ /* Init this thread. */
+ if (odp_init_local(ODP_THREAD_CONTROL)) {
+ err = 1;
+ EXAMPLE_ERR("ODP local init failed.\n");
+ goto err_global;
+ }
+
+ num_workers = MAX_WORKERS;
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
+
+ shm_glbls = odp_shm_reserve("test_globals", sizeof(test_globals_t),
+ ODP_CACHE_LINE_SIZE, 0);
+ if (ODP_SHM_INVALID == shm_glbls) {
+ err = 1;
+ EXAMPLE_ERR("Error: shared mem reserve failed.\n");
+ goto err;
+ }
+
+ log_enries_num = num_workers * (ITERATION_NUM + num_workers);
+ log_size = sizeof(log_entry_t) * log_enries_num;
+ shm_log = odp_shm_reserve("test_log", log_size, ODP_CACHE_LINE_SIZE, 0);
+ if (ODP_SHM_INVALID == shm_log) {
+ err = 1;
+ EXAMPLE_ERR("Error: shared mem reserve failed.\n");
+ goto err;
+ }
+
+ gbls = odp_shm_addr(shm_glbls);
+ gbls->thread_num = num_workers;
+ gbls->iteration_num = ITERATION_NUM;
+ odp_atomic_store_u32(&gbls->iteration_counter, 0);
+ odp_atomic_store_u32(&gbls->id_counter, 1);
+ odp_atomic_store_u32(&gbls->log_counter, 0);
+ odp_atomic_store_u32(&gbls->err_counter, 0);
+ gbls->log_enries_num = log_enries_num;
+ gbls->log = odp_shm_addr(shm_log);
+ odp_barrier_init(&gbls->start_barrier, num_workers);
+ odp_barrier_init(&gbls->end_barrier, num_workers);
+ memset(gbls->log, 0, log_size);
+
+ params.buf.size = sizeof(timestamp_event_t);
+ params.buf.align = ODP_CACHE_LINE_SIZE;
+ params.buf.num = num_workers;
+ params.type = ODP_POOL_BUFFER;
+
+ pool = odp_pool_create("time buffers pool", &params);
+ if (pool == ODP_POOL_INVALID) {
+ err = 1;
+ EXAMPLE_ERR("Pool create failed.\n");
+ goto err;
+ }
+
+ /* Create and launch worker threads */
+ odph_linux_pthread_create(thread_tbl, &cpumask,
+ run_thread, gbls, ODP_THREAD_WORKER);
+
+ /* Wait for worker threads to exit */
+ odph_linux_pthread_join(thread_tbl, num_workers);
+
+ print_log(gbls);
+
+err:
+ if (pool != ODP_POOL_INVALID)
+ if (odp_pool_destroy(pool))
+ err = 1;
+
+ if (shm_log != ODP_SHM_INVALID)
+ if (odp_shm_free(shm_log))
+ err = 1;
+
+ if (shm_glbls != ODP_SHM_INVALID)
+ if (odp_shm_free(shm_glbls))
+ err = 1;
+
+ if (odp_term_local())
+ err = 1;
+err_global:
+ if (odp_term_global())
+ err = 1;
+end:
+ if (err) {
+ EXAMPLE_ERR("Err: ODP global time test failed\n\n");
+ return -1;
+ }
+
+ printf("ODP global time test complete\n\n");
+ return 0;
+}
diff --git a/test/performance/odp_l2fwd_run b/test/performance/odp_l2fwd_run
index 001d8c27..cab97a8c 100755
--- a/test/performance/odp_l2fwd_run
+++ b/test/performance/odp_l2fwd_run
@@ -48,12 +48,20 @@ fi
run_l2fwd()
{
- setup_pktio_env
+ setup_pktio_env clean # install trap to call cleanup_pktio_env
+
if [ $? -ne 0 ]; then
echo "setup_pktio_env error $?"
exit $TEST_SKIPPED
fi
+ type odp_generator > /dev/null
+ if [ $? -ne 0 ]; then
+ echo "odp_generator not installed. Aborting."
+ cleanup_pktio_env
+ exit 1
+ fi
+
#@todo: limit odp_generator to cores
#https://bugs.linaro.org/show_bug.cgi?id=1398
(odp_generator${EXEEXT} -I $IF0 \
@@ -88,9 +96,6 @@ run_l2fwd()
rm -f $LOG
cleanup_pktio_env
- if [ $? -ne 0 ]; then
- echo "cleanup_pktio_env error $?"
- fi
exit $ret
}