Signed-off-by: Daniele Di Proietto <ddiproie...@vmware.com> --- tests/automake.mk | 2 + tests/test-stats.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + tests/threadstats.at | 4 ++ 4 files changed, 169 insertions(+) create mode 100644 tests/test-stats.c create mode 100644 tests/threadstats.at
diff --git a/tests/automake.mk b/tests/automake.mk index 1f13230..37c232f 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -30,6 +30,7 @@ TESTSUITE_AT = \ tests/aes128.at \ tests/unixctl-py.at \ tests/uuid.at \ + tests/threadstats.at \ tests/json.at \ tests/jsonrpc.at \ tests/jsonrpc-py.at \ @@ -237,6 +238,7 @@ tests_ovstest_SOURCES = \ tests/test-rstp.c \ tests/test-sflow.c \ tests/test-sha1.c \ + tests/test-stats.c \ tests/test-stp.c \ tests/test-util.c \ tests/test-uuid.c \ diff --git a/tests/test-stats.c b/tests/test-stats.c new file mode 100644 index 0000000..f009bcf --- /dev/null +++ b/tests/test-stats.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include "fatal-signal.h" +#include "ovstest.h" +#include "ovs-thread.h" +#include "ovs-thread-stats.h" + +enum {N_WRITES = 100000}; +enum {N_READS = 100}; +struct info_thread +{ + int n_create; /* How many stats buckets should I create? */ + int n_waste; /* How many stats buckets should I create and destroy? */ + int n_total; /* How many stats buckets are there(minimum)? */ + struct ovs_barrier barrier; +}; + +static void +aggr_cb(void *aux, struct ovsthread_stats_bucket *b) +{ + uint64_t *i = (uint64_t *)aux; + *i += b->data[0]; +} + +static void * +stats_writer(void *aux_) +{ + struct info_thread *aux = aux_; + int *buckets; + int i,j; + + buckets = xmalloc(aux->n_create * sizeof(*buckets)); + + for (i = 0; i < aux->n_create; i++) { + buckets[i] = ovsthread_stats_create_bucket(); + } + + ovs_barrier_block(&aux->barrier); + + for (j = 0; j < N_WRITES; j++) { + for (i = 0; i < aux->n_create; i++) { + struct ovsthread_stats_bucket *b; + uint32_t seq; + + b = ovsthread_stats_get_bucket(buckets[i], &seq); + b->data[0]++; + ovsthread_stats_bucket_done(b, seq); + } + } + + for (i = 0; i < aux->n_create; i++) { + uint64_t v = 0; + ovsthread_stats_aggregate(buckets[i], &v, aggr_cb); + ovs_assert(v == N_WRITES); + } + + ovs_barrier_block(&aux->barrier); + + for (i = 0; i < aux->n_create; i++) { + ovsthread_stats_destroy_bucket(buckets[i]); + } + + ovsthread_stats_create_bucket(); + return NULL; +} + +static void * +stats_reader(void *aux_) +{ + struct info_thread *aux = aux_; + int i,j; + + for (i = 0; i < aux->n_waste; i++) { + int b = ovsthread_stats_create_bucket(); + ovsthread_stats_destroy_bucket(b); + } + + ovs_barrier_block(&aux->barrier); + + /* XXX this works because buckets id are small numbers. */ + for (j = 0; j < N_READS; j++) { + for (i = 0; i < aux->n_total; i++) { + uint64_t v = 0; + ovsthread_stats_aggregate(i, &v, aggr_cb); + ovs_assert(v <= N_WRITES); + } + } + + ovs_barrier_block(&aux->barrier); + + for (j = 0; j < N_READS; j++) { + for (i = 0; i < aux->n_total; i++) { + uint64_t v = 0; + ovsthread_stats_aggregate(i, &v, aggr_cb); + ovs_assert(v == N_WRITES || v == 0); + } + } + + return NULL; +} + +static void +test_stats(int n_readers, int n_writers) +{ + int i; + pthread_t *readers, *writers; + struct info_thread t; + + t.n_create = 20; + t.n_total = 20 * n_writers; + t.n_waste = 5; + + ovs_barrier_init(&t.barrier, n_readers + n_writers + 1); + + readers = xmalloc(n_readers * sizeof *readers); + writers = xmalloc(n_writers * sizeof *writers); + + for (i = 0; i < n_writers; i++) { + writers[i] = ovs_thread_create("writer", stats_writer, &t); + } + for (i = 0; i < n_readers; i++) { + readers[i] = ovs_thread_create("reader", stats_reader, &t); + } + + ovs_barrier_block(&t.barrier); + + ovs_barrier_block(&t.barrier); + + for (i = 0; i < n_writers; i++) { + xpthread_join(writers[i], NULL); + } + for (i = 0; i < n_readers; i++) { + xpthread_join(readers[i], NULL); + } + + ovs_barrier_destroy(&t.barrier); +} + +static void +test_stats_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + fatal_signal_init(); + test_stats(5, 5); +} + +OVSTEST_REGISTER("test-stats", test_stats_main); diff --git a/tests/testsuite.at b/tests/testsuite.at index 8712277..2fddcc9 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -139,6 +139,7 @@ m4_include([tests/file_name.at]) m4_include([tests/aes128.at]) m4_include([tests/unixctl-py.at]) m4_include([tests/uuid.at]) +m4_include([tests/threadstats.at]) m4_include([tests/json.at]) m4_include([tests/jsonrpc.at]) m4_include([tests/jsonrpc-py.at]) diff --git a/tests/threadstats.at b/tests/threadstats.at new file mode 100644 index 0000000..24f7982 --- /dev/null +++ b/tests/threadstats.at @@ -0,0 +1,4 @@ +AT_BANNER([Per thread statistics]) +AT_SETUP([multiple readers/writers]) +AT_CHECK([ovstest test-stats], [0], [], []) +AT_CLEANUP -- 2.1.0.rc1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev