[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