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

Dwight Engen dwight.engen at oracle.com
Mon Sep 16 20:17:54 UTC 2013


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