On 18 August 2014 16:30, Stuart Haslam <[email protected]> wrote:
> 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

Not entirely true and I did thought about using odp_example.
odp_example does use timer api (clock_gettime) which I don't want to
call from isolated thread. Therefore choose to keep dummy (explicitly
mentioned in writeup) thread looping for x time.

More appropriate test application is l2fwd, where I am doing isolation.

There is a readme (in next patch) which very much informs NOT to use
odp method of cpuset for thread pinning instead use script. I could
choose to add job enqueue/dequeue in while loop But in next patch.

> 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.

Right, I though so. I'll do.
>
> [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.
>

Nope. Not in this case, I want to create thread on any of cores based
on arg_list, That may be look like this -
-l 2,3,5,6 OR -l 3,5,6,7

Also changing the order helps me to test my isolation script.

> --
> Stuart.
>

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

Reply via email to