diff options
author | Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> | 2016-01-15 17:03:56 +0200 |
---|---|---|
committer | Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> | 2016-01-15 17:03:56 +0200 |
commit | 41a0e90cf821254be7cf0d528b5c86cc08d22999 (patch) | |
tree | 58c1b714a1400401728359d05352864ecd8c4405 | |
parent | 3208b66cfeb195d184ab9756d2ca5bb1fb58f76d (diff) | |
parent | 3b7f7085fd128c0e32756b1d35b898c8aa5a74c0 (diff) |
Merge remote-tracking branch 'linaro-odp/master' into new_master
-rw-r--r-- | DEPENDENCIES | 7 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | doc/Makefile.am | 7 | ||||
-rw-r--r-- | doc/application-api-guide/Makefile.am | 5 | ||||
-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.am | 2 | ||||
-rw-r--r-- | example/classifier/odp_classifier.c | 3 | ||||
-rw-r--r-- | example/time/.gitignore | 1 | ||||
-rw-r--r-- | example/time/Makefile.am | 10 | ||||
-rw-r--r-- | example/time/time_global_test.c | 358 | ||||
-rwxr-xr-x | test/performance/odp_l2fwd_run | 13 |
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", ¶ms); + 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 } |