[lxc-devel] [PATCH] add arguments with getopt to concurrent tester

Serge Hallyn serge.hallyn at ubuntu.com
Mon Sep 16 21:40:48 UTC 2013


Quoting Dwight Engen (dwight.engen at oracle.com):
> - add ability to run for multiple iterations
> - can also run non-threaded for comparison to threaded case
> 
> Signed-off-by: Dwight Engen <dwight.engen at oracle.com>

Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>

> ---
> Hi Guys,
> 
> Serge I hope you don't mind I changed this to use getopt since there
> are a couple of things I'm using it for at the moment (ie. fixing up
> the fd leaks in the new cgroup code, patch for that will follow in a
> bit). Having it be able to do a couple iterations is handy for use
> with valgrind also.
> 
>  src/tests/concurrent.c | 148 ++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 116 insertions(+), 32 deletions(-)
> 
> diff --git a/src/tests/concurrent.c b/src/tests/concurrent.c
> index 7cf86c4..85b423b 100644
> --- a/src/tests/concurrent.c
> +++ b/src/tests/concurrent.c
> @@ -15,14 +15,46 @@
>   * with this program; if not, write to the Free Software Foundation, Inc.,
>   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>   */
> +
> +#include <limits.h>
>  #include <stdio.h>
>  #include <pthread.h>
> +#include <unistd.h>
> +#define _GNU_SOURCE
> +#include <getopt.h>
>  
>  #include "../lxc/lxccontainer.h"
>  
> -#define NTHREADS 5
> +static int nthreads = 5;
> +static int iterations = 1;
> +static int quiet = 0;
> +static int delay = 0;
> +static const char *template = "busybox";
> +
> +static struct option options[] = {
> +    { "threads",     required_argument, NULL, 'j' },
> +    { "iterations",  required_argument, NULL, 'i' },
> +    { "template",    required_argument, NULL, 't' },
> +    { "delay",       required_argument, NULL, 'd' },
> +    { "quiet",       no_argument,       NULL, 'q' },
> +    { "help",        no_argument,       NULL, '?' },
> +    { 0, 0, 0, 0 },
> +};
>  
> -char *template = "busybox";
> +static void usage(void) {
> +    fprintf(stderr, "Usage: lxc-test-concurrent [OPTION]...\n\n"
> +        "Common options :\n"
> +        "  -j, --threads=N      Threads to run concurrently\n"
> +        "                       (default: 5, use 1 for no threading)\n"
> +        "  -i, --iterations=N   Number times to run the test (default: 1)\n"
> +        "  -t, --template=t     Template to use (default: busybox)\n"
> +        "  -d, --delay=N        Delay in seconds between start and stop\n"
> +        "  -q, --quiet          Don't produce any output\n"
> +        "  -?, --help           Give this help list\n"
> +        "\n"
> +        "Mandatory or optional arguments to long options are also mandatory or optional\n"
> +        "for any corresponding short options.\n\n");
> +}
>  
>  struct thread_args {
>      int thread_id;
> @@ -30,16 +62,21 @@ struct thread_args {
>      char *mode;
>  };
>  
> -void * concurrent(void *arguments) {
> -    char name[4];
> +static void do_function(void *arguments)
> +{
> +    char name[NAME_MAX+1];
>      struct thread_args *args = arguments;
>      struct lxc_container *c;
>  
> -    sprintf(name, "%d", args->thread_id);
> +    sprintf(name, "lxc-test-concurrent-%d", args->thread_id);
>  
> +    args->return_code = 1;
>      c = lxc_container_new(name, NULL);
> +    if (!c) {
> +        fprintf(stderr, "Unable to instantiate container (%s)\n", name);
> +        return;
> +    }
>  
> -    args->return_code = 1;
>      if (strcmp(args->mode, "create") == 0) {
>          if (!c->is_defined(c)) {
>              if (!c->create(c, template, NULL, NULL, 1, NULL)) {
> @@ -58,6 +95,7 @@ void * concurrent(void *arguments) {
>                  fprintf(stderr, "Waiting the container (%s) to start failed...\n", name);
>                  goto out;
>              }
> +            sleep(delay);
>          }
>      } else if(strcmp(args->mode, "stop") == 0) {
>          if (c->is_defined(c) && c->is_running(c)) {
> @@ -81,49 +119,95 @@ void * concurrent(void *arguments) {
>      args->return_code = 0;
>  out:
>      lxc_container_put(c);
> -    pthread_exit(NULL);
>  }
>  
> +static void *concurrent(void *arguments)
> +{
> +    do_function(arguments);
> +    pthread_exit(NULL);
> +}
>  
>  int main(int argc, char *argv[]) {
> -    int i, j;
> +    int i, j, iter, opt;
>      pthread_attr_t attr;
> -    pthread_t threads[NTHREADS];
> -    struct thread_args args[NTHREADS];
> +    pthread_t *threads;
> +    struct thread_args *args;
>  
>      char *modes[] = {"create", "start", "stop", "destroy", NULL};
>  
> -    if (argc > 1)
> -	    template = argv[1];
> -
>      pthread_attr_init(&attr);
> -    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
>  
> -    for (i = 0; modes[i];i++) {
> -        printf("Executing (%s) for %d containers...\n", modes[i], NTHREADS);
> -        for (j = 0; j < NTHREADS; j++) {
> -            args[j].thread_id = j;
> -            args[j].mode = modes[i];
> -
> -            if (pthread_create(&threads[j], &attr, concurrent, (void *) &args[j]) != 0) {
> -                perror("pthread_create() error");
> -                exit(EXIT_FAILURE);
> -            }
> +    while ((opt = getopt_long(argc, argv, "j:i:t:d:q", options, NULL)) != -1) {
> +        switch(opt) {
> +        case 'j':
> +            nthreads = atoi(optarg);
> +            break;
> +        case 'i':
> +            iterations = atoi(optarg);
> +            break;
> +        case 't':
> +            template = optarg;
> +            break;
> +        case 'd':
> +            delay = atoi(optarg);
> +            break;
> +        case 'q':
> +            quiet = 1;
> +            break;
> +        default: /* '?' */
> +            usage();
> +            exit(EXIT_FAILURE);
>          }
> +    }
> +
> +    threads = malloc(sizeof(*threads) * nthreads);
> +    args = malloc(sizeof(*args) * nthreads);
> +    if (threads == NULL || args == NULL) {
> +        fprintf(stderr, "Unable malloc enough memory for %d threads\n", nthreads);
> +        exit(EXIT_FAILURE);
> +    }
>  
> -        for (j = 0; j < NTHREADS; j++) {
> -            if ( pthread_join(threads[j], NULL) != 0) {
> -                perror("pthread_join() error");
> -                exit(EXIT_FAILURE);
> +    for (iter = 1; iter <= iterations; iter++) {
> +        int fd;
> +        fd = open("/", O_RDONLY);
> +        if (!quiet)
> +            printf("\nIteration %d/%d maxfd:%d\n", iter, iterations, fd);
> +        close(fd);
> +
> +        for (i = 0; modes[i];i++) {
> +            if (!quiet)
> +                printf("Executing (%s) for %d containers...\n", modes[i], nthreads);
> +            for (j = 0; j < nthreads; j++) {
> +                args[j].thread_id = j;
> +                args[j].mode = modes[i];
> +
> +                if (nthreads > 1) {
> +                    if (pthread_create(&threads[j], &attr, concurrent, (void *) &args[j]) != 0) {
> +                        perror("pthread_create() error");
> +                        exit(EXIT_FAILURE);
> +                    }
> +                } else {
> +                    do_function(&args[j]);
> +                }
>              }
> -            if (args[j].return_code) {
> -                perror("thread returned an error");
> -                exit(EXIT_FAILURE);
> +    
> +            for (j = 0; j < nthreads; j++) {
> +                if (nthreads > 1) {
> +                    if (pthread_join(threads[j], NULL) != 0) {
> +                        perror("pthread_join() error");
> +                        exit(EXIT_FAILURE);
> +                    }
> +                }
> +                if (args[j].return_code) {
> +                    fprintf(stderr, "thread returned error %d", args[j].return_code);
> +                    exit(EXIT_FAILURE);
> +                }
>              }
>          }
> -        printf("\n");
>      }
>  
> +    free(args);
> +    free(threads);
>      pthread_attr_destroy(&attr);
>      exit(EXIT_SUCCESS);
>  }
> -- 
> 1.8.1.4
> 




More information about the lxc-devel mailing list