On Mon, Aug 18, 2014 at 08:41:00AM +0100, Santosh Shukla wrote:
> Test application to run odp dummy dp thread
> on no_hz_full kernel mode for few seconds.
> 
> - Create 2 threads, running in loop for few seconds.
> - Mask timer thread.
> 
> Signed-off-by: Santosh Shukla <[email protected]>
> ---
> Note :
> - Patch set based on Maxim's v2 patch under discussion
>     "implement-odp_init_global-init-mask.patch"
> - Open for review feedback however wont merge due
>   above dependancy.
> - More isolation specific changes seen at
> https://git.linaro.org/people/santosh.shukla/odp.git
> 
>  configure.ac                      |    1 +
>  example/Makefile.am               |    2 +-
>  example/isolation/Makefile.am     |    5 +
>  example/isolation/odp_isolation.c |  232 
> +++++++++++++++++++++++++++++++++++++
>  4 files changed, 239 insertions(+), 1 deletion(-)
>  create mode 100644 example/isolation/Makefile.am
>  create mode 100644 example/isolation/odp_isolation.c
> 
> diff --git a/configure.ac b/configure.ac
> index 74713a7..2b6758b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -142,6 +142,7 @@ AC_CONFIG_FILES([Makefile
>                example/packet/Makefile
>                example/packet_netmap/Makefile
>                example/timer/Makefile
> +              example/isolation/Makefile
>                test/Makefile
>                test/api_test/Makefile
>                pkgconfig/libodp.pc])
> diff --git a/example/Makefile.am b/example/Makefile.am
> index 01a3305..4cb4a23 100644
> --- a/example/Makefile.am
> +++ b/example/Makefile.am
> @@ -1 +1 @@
> -SUBDIRS = generator l2fwd odp_example packet packet_netmap timer
> +SUBDIRS = generator l2fwd odp_example packet packet_netmap timer isolation
> diff --git a/example/isolation/Makefile.am b/example/isolation/Makefile.am
> new file mode 100644
> index 0000000..7e39773
> --- /dev/null
> +++ b/example/isolation/Makefile.am
> @@ -0,0 +1,5 @@
> +include $(top_srcdir)/example/Makefile.inc
> +
> +bin_PROGRAMS = odp_isolation
> +
> +dist_odp_isolation_SOURCES = odp_isolation.c
> diff --git a/example/isolation/odp_isolation.c 
> b/example/isolation/odp_isolation.c
> new file mode 100644
> index 0000000..8d8fffc
> --- /dev/null
> +++ b/example/isolation/odp_isolation.c
> @@ -0,0 +1,232 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +/**
> + * @file
> + *
> + * @example  odp_isol_test.c ODP isolation example application
> + */
> +
> +#include <string.h>
> +#include <stdlib.h>
> +
> +/* ODP main header */
> +#include <odp.h>
> +
> +/* ODP helper for Linux apps */
> +#include <helper/odp_linux.h>
> +
> +/* GNU lib C */
> +#include <getopt.h>
> +
> +#define MAX_WORKERS  32      /**< Max worker threads */
> +
> +/**
> + * Parsed command line application arguments
> + */
> +typedef struct {
> +     int core_count; /**< Core count*/
> +     char **core_name;       /**< Array of pointers to core name */
> +} appl_args_t;
> +
> +/**
> + * @internal Print help
> + */
> +static void print_usage(void)
> +{
> +     printf("\n\nUsage: ./odp_isolation [options]\n");
> +     printf("Options:\n");
> +     printf("  -l, --cpulist <cpu number in comma separated fashion>\n");
> +     printf("  -h, --help              this help\n");
> +     printf("\n\n");
> +}
> +
> +/**
> + * @internal Worker thread
> + *
> + * @param arg  Arguments
> + *
> + * @return NULL on failure
> + */
> +static void *run_thread(void *arg)
> +{
> +     int thr;
> +     unsigned long long tick = 0;
> +     int counter = 0;
> +
> +     thr = odp_thread_id();
> +
> +     printf("Thread %i starts on core %i\n", thr, odp_thread_core());
> +
> +     /* loop for some duration then exit */
> +     do {
> +             tick++;
> +
> +             if (tick > 10000000) {
> +
> +                     tick = 0;
> +                     counter++;
> +             }
> +
> +             if (counter == 1000)
> +                     break;
> +     } while (1);
> +
> +     return arg;
> +}

I'm not sure it's worth adding an example application that does nothing.
Isolation is not be something the application needs explicit knowledge
of so having an example app demonstrating it is a bit odd. All of the
existing examples / tests should be capable of being run isolated.

For this test you could start with odp_example as it has no dependencies
and will exit after some time - if you need it to run for a particular
amount of time you could add an argument for that.

> +
> +/**
> + * @internal Parse arguments
> + *
> + * @param argc  Argument count
> + * @param argv  Argument vector
> + * @param args  Test arguments
> + */
> +static void parse_args(int argc, char *argv[], appl_args_t *args)
> +{
> +     int opt;
> +     int long_index;
> +     char *names, *str, *token, *save;
> +     size_t len;
> +     int i;
> +
> +     static struct option longopts[] = {
> +             {"cpulists", required_argument, NULL, 'l'}, /* return 'l' */
> +             {"help", no_argument, NULL, 'h'}, /* return 'h' */
> +             {NULL, 0, NULL, 0}
> +     };
> +
> +     while (1) {
> +             opt = getopt_long(argc, argv, "+l:h", longopts, &long_index);
> +
> +             if (opt == -1)
> +                     break;  /* No more options */
> +
> +             switch (opt) {
> +             case 'l':
> +                     len = strlen(optarg);
> +                     if (len == 0) {
> +                             print_usage();
> +                             exit(EXIT_FAILURE);
> +                     }
> +                     len += 1;       /* add room for '\0' */
> +
> +                     names = malloc(len);
> +                     if (names == NULL) {
> +                             print_usage();
> +                             exit(EXIT_FAILURE);
> +                     }
> +
> +                     /* count the number of tokens separated by ',' */
> +                     strcpy(names, optarg);
> +                     for (str = names, i = 0;; str = NULL, i++) {
> +                             token = strtok_r(str, ",", &save);
> +                             if (token == NULL)
> +                                     break;
> +                     }
> +                     args->core_count = i;
> +
> +                     if (args->core_count == 0) {
> +                             print_usage();
> +                             exit(EXIT_FAILURE);
> +                     }
> +                     /* allocate storage for the if names */
> +                     args->core_name =
> +                             calloc(args->core_count, sizeof(char *));
> +
> +                     /* store the if names (reset names string) */
> +                     strcpy(names, optarg);
> +                     for (str = names, i = 0;; str = NULL, i++) {
> +                             token = strtok_r(str, ",", &save);
> +                             if (token == NULL)
> +                                     break;
> +                             args->core_name[i] = token;
> +                     }
> +                     break;
> +

It would be better to change the behaviour of the existing -c
argument used in most of the examples from being a core count to
something similar to what you've done with -l here. Other related
applications (taskset [1], DPDK [2]) use -c to provide either a core
mask or a list.

[1] http://linux.die.net/man/1/taskset
[2] http://www.dpdk.info/ml/archives/dev/2014-April/002173.html

> +             case 'h':
> +                     print_usage();
> +                     exit(EXIT_SUCCESS);
> +                     break;
> +
> +             default:
> +                     break;
> +             }
> +     }
> +}
> +
> +/**
> + * Isolation test application
> + */
> +int main(int argc, char *argv[])
> +{
> +     odp_linux_pthread_t thread_tbl[MAX_WORKERS];
> +     appl_args_t args;
> +     int thr_id;
> +     int num_workers;
> +     int first_core;
> +     int i;
> +
> +     printf("\nODP isolation test application\n");
> +
> +     memset(&args, 0, sizeof(args));
> +     parse_args(argc, argv, &args);
> +
> +     memset(thread_tbl, 0, sizeof(thread_tbl));
> +
> +     /*
> +      * Don't need timer init for isolation, so mask them.
> +      */
> +     if (odp_init_global(ODP_INIT_F_ALL & ~ODP_INIT_F_TIMER)) {
> +             printf("ODP global init failed.\n");
> +             return -1;
> +     }
> +
> +     printf("\n");
> +     printf("ODP system info\n");
> +     printf("---------------\n");
> +     printf("ODP API version: %s\n",        odp_version_api_str());
> +     printf("CPU model:       %s\n",        odp_sys_cpu_model_str());
> +     printf("CPU freq (hz):   %"PRIu64"\n", odp_sys_cpu_hz());
> +     printf("Cache line size: %i\n",        odp_sys_cache_line_size());
> +     printf("Max core count:  %i\n",        odp_sys_core_count());
> +
> +     printf("\n");
> +
> +     /* A worker thread per core */
> +     num_workers = odp_sys_core_count();
> +
> +     if (args.core_count)
> +             num_workers = args.core_count;
> +
> +     /* force to max core count */
> +     if (num_workers > MAX_WORKERS)
> +             num_workers = MAX_WORKERS;
> +
> +     printf("num worker threads: %i\n", num_workers);
> +
> +     /*
> +      * Init this thread.
> +      * */
> +     thr_id = odp_thread_create(0);
> +     odp_init_local(thr_id);
> +
> +     for (i=0; i<num_workers; i++) {
> +
> +             first_core = atoi(args.core_name[i]);
> +             /* Create and launch worker threads */
> +             odp_linux_pthread_create(&thread_tbl[i], 1, first_core,
> +                                      run_thread, NULL);
> +     }
> +

I wonder if changing odp_linux_pthread_create to take an array of cores
rather than just the first core is a better way to go. A quick grep
through the existing examples / tests shows almost all callers provide 1
for the number of cores, so it's not currently being used as expected.

-- 
Stuart.


_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to