From a49daa2ef8b4210add3d2f9f23259b5cf7a7ebd6 Mon Sep 17 00:00:00 2001 From: Lassi Marttala Date: Fri, 20 Jan 2012 15:27:19 +0100 Subject: Initial version of dlt-test-multi-process --- src/tests/dlt-test-multi-process.c | 384 +++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100755 src/tests/dlt-test-multi-process.c (limited to 'src/tests/dlt-test-multi-process.c') diff --git a/src/tests/dlt-test-multi-process.c b/src/tests/dlt-test-multi-process.c new file mode 100755 index 0000000..d11cd1f --- /dev/null +++ b/src/tests/dlt-test-multi-process.c @@ -0,0 +1,384 @@ +/* + * DLT multi process tester + * @licence app begin@ + * + * Copyright (C) 2011, BMW AG - Lassi Marttala Lassi Marttala + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + * Public License, version 2.1, for more details. + * + * You should have received a copy of the GNU Lesser General Public License, version 2.1, along + * with this program; if not, see . + * + * Note that the copyright holders assume that the GNU Lesser General Public License, version 2.1, may + * also be applicable to programs even in cases in which the program is not a library in the technical sense. + * + * Linking DLT statically or dynamically with other modules is making a combined work based on DLT. You may + * license such other modules under the GNU Lesser General Public License, version 2.1. If you do not want to + * license your linked modules under the GNU Lesser General Public License, version 2.1, you + * may use the program under the following exception. + * + * As a special exception, the copyright holders of DLT give you permission to combine DLT + * with software programs or libraries that are released under any license unless such a combination is not + * permitted by the license of such a software program or library. You may copy and distribute such a + * system following the terms of the GNU Lesser General Public License, version 2.1, including this + * special exception, for DLT and the licenses of the other code concerned. + * + * Note that people who make modified versions of DLT are not obligated to grant this special exception + * for their modified versions; it is their choice whether to do so. The GNU Lesser General Public License, + * version 2.1, gives permission to release a modified version without this exception; this exception + * also makes it possible to release a modified version which carries forward this exception. + * + * @licence end@ + */ + +/******************************************************************************* +** ** +** SRC-MODULE: dlt-test-multi-process.c ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Lassi Marttala Lassi.LM.Marttala@partner.bmw.de ** +** ** +** PURPOSE : Stress test timing using multiple processes ** +** ** +** REMARKS : Requires POSIX fork() ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dlt.h" +#include "dlt_common.h" +#include "dlt-test-multi-process.h" + +// Constants +#define MAX_PROCS 100 +#define MAX_THREADS 100 + +// Structs +typedef struct { + int nmsgs; // Number of messages to send + int nprocs; // Number of processes to start + int nthreads; // Number of threads to start + int delay; // Delay between logs messages for each process + int delay_fudge; // Fudge the delay by 0-n to cause desynchronization +} s_parameters; + +typedef struct { + s_parameters params; + DltContext ctx; +} s_thread_data; + +// Forward declarations +void quit_handler(int signum); +void cleanup(); +void do_forks(s_parameters params); +void run_threads(s_parameters params); +void do_logging(s_thread_data *data); +int wait_for_death(); + +// State information +volatile sig_atomic_t in_handler = 0; + +// Globals for cleanup from main and signal handler +pid_t pids[MAX_PROCS]; +int pidcount = 0; + +/** + * Print instructions. + */ +void usage(char *prog_name) +{ + char version[255]; + dlt_get_version(version); + + printf("Usage: %s [options]\n", prog_name); + printf("Test application for stress testing the daemon with multiple processes and threads.\n"); + printf("%s\n", version); + printf("Options:\n"); + printf(" -m number Number of messages per thread to send.\n"); + printf(" -p number Number of processes to start. Max %d.\n", MAX_PROCS); + printf(" -t number Number of threads per process. Max %d.\n", MAX_THREADS); + printf(" -d delay Delay in milliseconds to wait between log messages.\n"); + printf(" -f delay Random fudge in milliseconds to add to delay.\n"); +} + +/** + * Set nice default values for parameters + */ +void init_params(s_parameters * params) { + params->nmsgs = 100; + params->nprocs = 10; + params->nthreads = 2; + params->delay = 1000; + params->delay_fudge = 100; +} + +/** + * Read the command line and modify parameters + */ +int read_cli(s_parameters *params, int argc, char **argv) +{ + int c; + opterr = 0; + while ((c = getopt (argc, argv, "m:p:t:d:f:")) != -1) + { + switch(c) + { + case 'm': + params->nmsgs = atoi(optarg); + break; + case 'p': + params->nprocs = atoi(optarg); + if(params->nprocs > MAX_PROCS) + { + fprintf(stderr, "Too many processes selected.\n"); + return -1; + } + break; + case 't': + params->nthreads = atoi(optarg); + if(params->nprocs > MAX_PROCS) + { + fprintf(stderr, "Too many threads selected.\n"); + return -1; + } + break; + case 'd': + params->delay = atoi(optarg); + break; + case 'f': + params->delay_fudge = atoi(optarg); + break; + case '?': + if(optopt == 'n' || optopt == 'd' || optopt == 'f') + { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } + else if(isprint(optopt)) + { + fprintf(stderr, "Unknown option '-%c'.\n", optopt); + } + else + { + fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt); + } + return -1; + break; + default: + abort(); + } + } + return 0; +} + +/** + * Entry point + */ +int main(int argc, char **argv) +{ + // Prepare parameters + s_parameters params; + init_params(¶ms); + if(read_cli(¶ms, argc, argv) != 0) { + usage(argv[0]); + exit(-1); + } + + // Launch the child processes + do_forks(params); + + // Register signal handlers + if(signal(SIGINT, quit_handler) == SIG_IGN) + signal(SIGINT, SIG_IGN); // C-c + if(signal(SIGHUP, quit_handler) == SIG_IGN) + signal(SIGHUP, SIG_IGN); // Terminal closed + if(signal(SIGTERM, quit_handler) == SIG_IGN) + signal(SIGTERM, SIG_IGN); // kill (nice) + + printf("Setup done. Listening. My pid: %d\n", getpid()); + fflush(stdout); + + int err = wait_for_death(); + cleanup(); + return err; +} + +/** + * Start the child processes + */ + +void do_forks(s_parameters params) +{ + int i; + + // Launch child processes + for(i=0;iparams.nmsgs; + pid_t mypid = getpid(); + + + srand(mypid); + + while(msgs_left-- > 0) + { + DLT_LOG(data->ctx, DLT_LOG_INFO, DLT_STRING(PAYLOAD_DATA)); + usleep(mksleep_time(data->params.delay, data->params.delay_fudge)); + } +} + +/** + * Start the threads and wait for them to return. + */ +void run_threads(s_parameters params) +{ + DltContext mycontext; + pthread_t thread[params.nthreads]; + s_thread_data thread_data; + char ctid[5]; + int i; + + srand(getpid()); + + DLT_REGISTER_APP(DMPT_NAME,"DLT daemon multi process test."); + sprintf(ctid,"%.2x", rand() & 0x0000ffff); + DLT_REGISTER_CONTEXT(mycontext, ctid, "Child in dlt-test-multi-process"); + + thread_data.params = params; + thread_data.ctx = mycontext; + + for(i=0;i 0) + { + int status; + pid_t w = waitpid(WAIT_ANY, &status, 0); + if(status < 0) + { + return -1; + } + else + { + int i; + for(i=0;i