void CharacterState_setCurrentScheme (SCharacterState *characterState, unsigned value) { assert(characterState != NULL); if (value >= characterState->schemeSize) { Log_output(1, "Error: Attempt to set %u value to current index of a %u-sized table\n", value, characterState->schemeSize); exit (EXIT_FAILURE); } characterState->currentScheme = value; }
static void Log_posttrace(int log_level, traceEntry* cur_entry) { if (((trace_output_level == -1) ? log_level >= trace_settings.trace_level : log_level >= trace_output_level)) { char* msg = NULL; if (trace_destination || trace_callback) msg = &Log_formatTraceEntry(cur_entry)[7]; Log_output(log_level, msg); } }
int Log_initialize(Log_nameValue* info) { int rc = -1; char* envval = NULL; if ((trace_queue = malloc(sizeof(traceEntry) * trace_settings.max_trace_entries)) == NULL) return rc; trace_queue_size = trace_settings.max_trace_entries; if ((envval = getenv("MQTT_C_CLIENT_TRACE")) != NULL && strlen(envval) > 0) { if (strcmp(envval, "ON") == 0 || (trace_destination = fopen(envval, "w")) == NULL) trace_destination = stdout; else { trace_destination_name = malloc(strlen(envval) + 1); strcpy(trace_destination_name, envval); trace_destination_backup_name = malloc(strlen(envval) + 3); sprintf(trace_destination_backup_name, "%s.0", trace_destination_name); } } if ((envval = getenv("MQTT_C_CLIENT_TRACE_MAX_LINES")) != NULL && strlen(envval) > 0) { max_lines_per_file = atoi(envval); if (max_lines_per_file <= 0) max_lines_per_file = 1000; } if ((envval = getenv("MQTT_C_CLIENT_TRACE_LEVEL")) != NULL && strlen(envval) > 0) { if (strcmp(envval, "MAXIMUM") == 0 || strcmp(envval, "TRACE_MAXIMUM") == 0) trace_settings.trace_level = TRACE_MAXIMUM; else if (strcmp(envval, "MEDIUM") == 0 || strcmp(envval, "TRACE_MEDIUM") == 0) trace_settings.trace_level = TRACE_MEDIUM; else if (strcmp(envval, "MINIMUM") == 0 || strcmp(envval, "TRACE_MEDIUM") == 0) trace_settings.trace_level = TRACE_MINIMUM; else if (strcmp(envval, "PROTOCOL") == 0 || strcmp(envval, "TRACE_PROTOCOL") == 0) trace_output_level = TRACE_PROTOCOL; else if (strcmp(envval, "ERROR") == 0 || strcmp(envval, "TRACE_ERROR") == 0) trace_output_level = LOG_ERROR; } Log_output(TRACE_MINIMUM, "========================================================="); Log_output(TRACE_MINIMUM, " Trace Output"); if (info) { while (info->name) { sprintf(msg_buf, "%s: %s", info->name, info->value); Log_output(TRACE_MINIMUM, msg_buf); info++; } } #if !defined(WIN32) struct stat buf; if (stat("/proc/version", &buf) != -1) { FILE* vfile; if ((vfile = fopen("/proc/version", "r")) != NULL) { int len; strcpy(msg_buf, "/proc/version: "); len = strlen(msg_buf); if (fgets(&msg_buf[len], sizeof(msg_buf) - len, vfile)) Log_output(TRACE_MINIMUM, msg_buf); fclose(vfile); } } #endif Log_output(TRACE_MINIMUM, "========================================================="); return rc; }
/** * @brief Main function * @param argc Number of arguments * @param **argv The arguments * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure */ int main (int argc, char ** argv) { unsigned i; int *process_pinning = NULL; int status; pid_t pid; unsigned nbprocess; SPipe *pipes; int res; int isOpenMP = 0; int iterationsDoneAlready = 0; unsigned currentExecRepet; unsigned execRepets, kernelId, nbKernels; printf("*************************************************************************************************\n"); printf("* |\\ /| ' ____ ____ ____ ____ ____ ____ ____\t*\n"); printf("* | \\ / | | | |____| | | | |____| | | | \\ | | |____| |____ |____|\t*\n"); printf("* | ' | | |____ | \\ |____| |____ | | |____| | \\ | |____ | | |____ | \\\t*\n"); printf("*\t\t\t\t\t\t\t\t\t\t\t\t*\n"); printf("*************************************************************************************************\n"); /* Handle options */ if (Option_handleHelpRequest (argc, argv) == 0) { return EXIT_SUCCESS; } /* Before anything, handle signal */ pushSignalHandler (SignalHandler_microlauncher); fprintf (stderr, "ML Start %d\n", getpid ()); Log_setOutput (stderr); Log_setVerbosity (8); /* Then, we need to generate the program data description */ SDescription *desc = Description_create (); /* Next set Log to stderr */ // Handle options Option_handleCommandLine (desc, argc, argv); /* Now that we have handled user customed values, let's set unset values to our defaults */ Description_setDefaults (desc); // Arguments verification if (Description_AssertValues (desc) == -1) { Log_output (-1, "Error: Exiting Microlauncher now...\n"); exit (EXIT_FAILURE); } // Warn the user Description_ShowWarnings (desc); // If the file PATH_TO_KILL exists, cancel the program (sleep_tight.h) escape_from_scary_killers (); /* If current architecture isn't good for us */ if (sizeof (unsigned long long) != 8) { Log_output (-1, "Error: Unsigned long long size != 64 bit ! Exiting...\n"); exit (EXIT_FAILURE); } /* Prepare the sleep tight signals */ if (sleep_tight_preparesignals() != 0) { Log_output (-1, "Error! Could not prepare Sleep Tight's signals! Aborting.\n"); exit(EXIT_FAILURE); } /* Now that the desc values have been all handled, we save them for possible resuming request */ resumeSave (desc); /* Allocate data for the pipes and process pinning */ nbprocess = Description_getNbProcess (desc); pipes = malloc (sizeof (*pipes) * nbprocess); assert (pipes != NULL); memset (pipes, 0, sizeof (*pipes) * nbprocess); /* Allocate process pinning table only if we're not in OpenMP mode as this mode doesn't pin CPUs */ isOpenMP = Description_getOmpPath (desc) != NULL; if (!isOpenMP) { process_pinning = malloc (sizeof (*process_pinning) * nbprocess); assert(process_pinning != NULL); memset (process_pinning, 0, sizeof (*process_pinning) * nbprocess); /* Process pinning initialization */ for (i = 0; i < nbprocess ; i++) { Log_output (-1, "Getting pinning %d: %d\n", i, Description_getPinningAt (desc, i)); process_pinning[i] = Description_getPinningAt (desc, i); } } /* Get the father aware of the number of experiments to be done by its children */ Description_setExperimentNumber (desc, getExperimentNumber (desc)); execRepets = Description_getExecuteRepets (desc); if (Description_getExecFileName (desc) != NULL) { nbKernels = 1; } else { nbKernels = Description_getKernelFileNamesTabSize (desc); } /* Multiple kernels handling */ for (kernelId = 0; kernelId < nbKernels; kernelId++) { if (Description_getExecFileName (desc) == NULL) { /* Setting the current kernel name to the current id we're running */ Description_setKernelCurrentFileId (desc, kernelId); Log_output (-1, "Current Kernel Execution : %s\n", Description_getKernelFileName (desc)); } /* Re-init to last known currentExecRepet value if we're resuming */ if (resumeInitCounter (¤tExecRepet, desc->temp_values.current_execute_repet)) { Log_output (-1, "Note: Resuming to last --executerepet value : %d\n", currentExecRepet); } else { currentExecRepet = 0; } /* Repeats Microlauncher --executerepet (argument) times */ for (; currentExecRepet < execRepets; currentExecRepet++) { if (resumeIsResuming ()) { resumeLoadCounters (desc); } /* If more than 1 execution repeat, get the user aware of current iteration */ if (execRepets > 1) { Log_output (-1, "\n\nMicrolaunch Repeat #%d\n", currentExecRepet+1); } /* Input file compilation */ compileInputFile (desc); /* Processes launch */ fprintf (stderr, "ML: %d -> Creating %d\n", getpid (), nbprocess); for (i = 0; i < nbprocess ; i++) { Pipe_generate (&pipes[i]); pid = fork (); if (pid == 0) { fprintf (stderr, "ML: %d: Creating son: %d\n", getppid (), getpid ()); //Start formatting strings: for the moment just exec arguments, exec name, and exec path Description_reformatStrings (desc, i); //If we must change directory char *res = Description_getExecPath (desc); if (res != NULL) { int chroot_res = chdir (res); if (chroot_res != 0) { perror (""); exit (EXIT_FAILURE); } } /* Push the signal handler : We're now in the child function */ pushSignalHandler (SignalHandler_child); /* Defines the process Id */ Description_setProcessId (desc, i); /* By default, we enable the printing and eval handling stuff for the first child */ if(i == 0 || Description_getAllPrintOut (desc) != 0) { Description_printingProcessEnable (desc); Description_processEvalHandlerEnable (desc); } /* If we have allprocess-output argument, then every process compute its counters */ if (Description_isAllProcessOutputEnabled (desc)) { Description_processEvalHandlerEnable (desc); } /* If we're not in OpenMP mode and we do pin the threads, we pin the processes on the machine's cores */ if (isOpenMP == 0 && Description_isThreadPinningEnabled (desc) != 0) { if (!Description_isCpuPinDefined (desc)) { Description_setCPUDest (desc, process_pinning[i]); } //Pin CPU if (Description_pinCPU (desc) == -1) { abort (); } } /* We save the pipes in the description for barrierS future calls (see benchmark.c) */ Description_setTubeSF (desc,pipes[i].sf); Description_setTubeFS (desc,pipes[i].fs); //Close the unused sides of pipes Pipe_closeChildUnusedSide ( &pipes[i] ); /* Are we launching an executable or do we want to launch a function in a dynamic library ? */ switch (Description_getSourceType (desc)) { case EXECUTABLE_FILE: /* EXEC MODE */ { Pipe_closeChildUnusedSide ( &pipes[i] ); status = Benchmark_Exec (desc, currentExecRepet); if (status != EXIT_SUCCESS) { abort (); } break; } case LIBRARY_FILE: case SOURCE_FILE: case ASSEMBLY_FILE: case OBJECT_FILE: /* KERNEL MODE */ { status = Benchmark_Wrapper (desc, currentExecRepet); if (status != EXIT_SUCCESS) { abort (); } break; } default: Log_output (-1, "Error: Unknown File source type, cannot launch benchmark, code %d\n", Description_getSourceType (desc)); exit (EXIT_FAILURE); } //We have finished, close the rest Pipe_closeChildUsedSide ( &pipes[i] ); // Take away the signal handler (child) popSignalHandler (); /* Son free stuff */ if (!isOpenMP) { free(process_pinning), process_pinning = NULL; } free(pipes), pipes = NULL; int isPrintingProcess = Description_isPrintingProcess (desc); //Destroy description Description_destroy (desc), desc = NULL; if (isPrintingProcess) { Log_output (-1, "Child process exiting now...\n"); } // Take away the signal handler (father) popSignalHandler (); exit (EXIT_SUCCESS); } else if(pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else { /* Close non-used side of each pipe */ Pipe_closeFatherUnusedSide ( &pipes[i] ); } } if (resumeIsResuming ()) { iterationsDoneAlready = desc->temp_values.curruns; } else { iterationsDoneAlready = 0; } /* Setting up the father Barrier */ unsigned max = benchmarkIterationsNumber (desc, iterationsDoneAlready); for (i = 0 ; i < max ; i++) { barrierF (pipes, nbprocess); } /* Close the rest of the pipes */ for (i = 0 ; i < nbprocess ; i++) { Pipe_closeFatherUsedSide ( &pipes[i] ); } /* Child processes wait */ for (i = 0 ; i < nbprocess ; i++) { waitpid (-1, &status, 0); res = WEXITSTATUS(status); if(res != EXIT_SUCCESS) { Log_output (-1, "Child exited with status %d, an error occured.\n", res); } if (WIFEXITED(status) == 0) { char buf[512]; snprintf (buf, 512, "Error: Child %d received a signal ", i); psignal (WTERMSIG (status), buf); } } desc->temp_values.current_execute_repet++; /* Disabling resume in the innermost loop of the father process because resuming has to be done just for the first iteration of each process loops */ resumeDisableResuming (); } } /* Job is done, let's create a file to tell the user so */ resumeSignalJobDone (desc); /* Free data */ free (pipes), pipes = NULL; if (!isOpenMP) { free (process_pinning), process_pinning = NULL; } if (Description_isSummaryEnabled (desc)) { if (generateSummary (desc) != -1) { Log_output (-1, "Info: A summary.xls file has been created in the %s folder.\n", Description_getOutputPath (desc)); } else { Log_output (-1, "Error: An error occured while creating summary file.\n"); } } Description_destroy ( desc ); Log_output(-1, "Father process exiting now...\n"); //Take away the signal handler popSignalHandler (); return EXIT_SUCCESS; }
/** * @brief Arguments handling : All the parameters of the program are handled here (expect from the special arguments which are handled before) * * @param desc the Description we are about to change to handle the special args * @param argc the number of arguments passed to the program * @param argv the strings table of arguments passed to the program */ static inline void Option_handleArguments (SDescription *desc, int argc, char *argv[]) { char *configFileName = Description_getConfigFile (desc); long val; int opt; FILE *f; unsigned m_nb_args; char **m_argv; // First, we have to parse the XML config file if (configFileName != NULL) { if (Config_parseXML (desc, configFileName) == -1) { Log_output (-1, "Error: An error occured while parsing the XML config file.\n"); exit (EXIT_FAILURE); } } // Then, we can now handle other arguments in the command line optind = 1; /* Then, the final values have to be those of the command line */ while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { switch (opt) { case 'a': // --summary Description_enableSummary(desc); break; case 'A': // --alloclib Description_setDynAllocLib(desc, optarg); break; case 'b': // --basename Description_setBaseName (desc, optarg); break; case 'B': // --verifylib Description_setVerificationLibraryName (desc, optarg); break; case 'c': // --cpupin parseCPUPinning (desc, optarg); break; case 'd': // --sizedummy val = Option_transformArgument (optarg); Description_setDummySize (desc, val); break; case 'D': // --output-dir Description_setOutputPath (desc, optarg); break; case 'e': // --endvector val = Option_transformArgument (optarg); Description_setEndVectorSize (desc, val); break; case 'f': // --kernelfunction Description_setDynamicFunctionName (desc, optarg); break; case 'F': // --no-eval-stack Description_disableEvalStack (desc); break; case 'g': // --output-same-dir Description_setOutputPath (desc, "."); break; case 'G': Description_setExecPath (desc, optarg); break; case 'i': // --stepvector val = Option_transformArgument (optarg); Description_setVectorSizeStep (desc, val); break; case 'I': // --info Description_parseInfoDisplayedInput (desc, optarg); break; case 'k': // --kernelname if (isFile (optarg)) { Description_setKernelFileNamesTabSize (desc, 1); Description_setKernelFileNameAt (desc, optarg, 0); } else if (isDirectory (optarg)) { parseDir (optarg, desc); } else { Log_output (-1, "Error: Cannot resolve kernel name filetype.\n"); exit (EXIT_FAILURE); } Description_setKernelFileName (desc, optarg); break; case 'l': // --logverbosity val = Option_transformArgument (optarg); Log_setVerbosity (val); break; case 'm': // --metarepetition val = Option_transformArgument (optarg); Description_setMetaRepetition (desc, val); break; case 'M': // --vectorspacing val = Option_transformArgument (optarg); Description_setVectorSpacing (desc, val); break; case 'N': // --no-output Description_setPromptOutputCsv (desc, 0); break; case 'o': // --log-output f = fopen (optarg, "w"); Log_setOutput (f); break; case 'O': // --nbprocess val = Option_transformArgument (optarg); if (Description_getNbProcess (desc) > 0 && Description_getNbProcess (desc) != val) { Log_output (-1, "Error: Number of processes already defined and not the same value\n"); exit (EXIT_FAILURE); } else { if (Description_getNbProcess (desc) < 0) { Description_setNbProcess (desc, val); } } break; case 'p': // --pagecollide val = Option_transformArgument (optarg); Description_setNbPagesForCollision (desc, val); break; case 'P': // --pagesize val = Option_transformArgument (optarg); Description_setPageSize (desc, val); break; case 'q': // --vectsurveyor parse_vect_surveyor (desc,optarg); break; case 'Q': // --executerepetition val = Option_transformArgument (optarg); Description_setExecuteRepets (desc, val); break; case 'r': // --repetition val = Option_transformArgument (optarg); Description_setRepetition (desc, val); break; case 's': // --startvector val = Option_transformArgument (optarg); Description_setStartVectorSize (desc, val); break; case 'S': // --maxstride val = Option_transformArgument (optarg); Description_setMaxStride (desc, val); break; case 't': // --omppath Description_setOmpPath (desc, optarg); break; case 'T': // --execname Description_setExecFileName (desc, optarg); break; case 'u': // --execargs m_argv = getArgs (desc, optarg, &m_nb_args); Description_setExecArgc (desc, m_nb_args); Description_setExecArgv (desc, m_argv); break; case 'U': // --suppress-output Description_setSuppressOutput (desc, 1); break; case 'v': // --iteration-count val = Option_transformArgument (optarg); Description_setIterationCount (desc, val); Description_iterationCountEnable (desc); break; case 'V': // --execoutput Description_setOutputFileStream (desc, optarg); break; case 'w': // --initfunction Description_setKernelInitFunctionName (desc, optarg); break; case 'W': // --data-size /* If user specifies "float", let's allocate sizeof(float) */ if (strncmp ("float", optarg, STRBUF_MAXLEN) == 0) { Description_setVectorElementSize (desc, sizeof (float)); } /* If he specifies "double", let's allocate sizeof(double) */ else if (strncmp ("double", optarg, STRBUF_MAXLEN) == 0) { Description_setVectorElementSize (desc, sizeof (double)); } /* Else, he must have specified a numeric constant */ else { val = Option_transformArgument (optarg); Description_setVectorElementSize (desc, val); } break; case 'x': // --nbsizes Description_nbSizesEnable (desc); parseVectorSizes (desc, optarg); break; case 'X': // --no-thread-pin Description_pinThreadDisable (desc); break; case 'y': // --all-print-out Description_setAllPrintOut (desc, 1); break; case 'Y': // --all-metric-output Description_allProcessOutputEnable (desc); break; case 'z': // --resumeid val = Option_transformArgument (optarg); Description_setResumeId (desc, val); break; default: assert (argv != NULL && argv[0] != 0); break; } } }
/** * @brief Some arguments must be handled before other, for allocation or specific purpose ; here is their handling * * @param desc the Description we are about to change to handle the special args * @param argc the number of arguments passed to the program * @param argv the strings table of arguments passed to the program * @return 1 if we have to abort the command line handling, 0 else */ static inline int Option_handleSpecialArgs (SDescription *desc, int argc, char *argv[]) { int opt; long val; //By default set resume to 0 Description_setResumeId (desc, 0); // First, we have to load resume stuff if any optind = 1; while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Is the resume id specified? if(opt == 'z') { val = Option_transformArgument (optarg); Description_setResumeId (desc, val); } } optind = 1; while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Are we resuming? if(opt == 'R') { if (resumeLoad (desc) == -1 || resumeLoadCounters (desc) == -1) // Failed to resume { Log_output(-1, "Error: Failed to resume.\n"); exit(EXIT_FAILURE); } else // Resumed successfully { resumeEnableResuming (); Description_setResuming (desc, 1); desc->number_of_resumes++; Log_output (-1, "Loaded resume values successfully. (%dnth resume)\n", desc->number_of_resumes); } return 1; } } /* Special argument : Config file ; if any, we have to load it before loading other command line arglist */ optind = 1; while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Check in the command line arglist if(opt == 'C') { Description_setConfigFile (desc, optarg); /* Then, if any, we have to parse special args before those of the command line */ if (Config_parseXMLSpecialArgs (desc, desc->configFileName) == -1) { Log_output (-1, "An error occured while parsing XML config file.\n"); exit (EXIT_FAILURE); } } } /* Special argument : nbVectors : it must be allocated before dealing with anything else (calling setNbVectors () do a lot of allocation stuff) */ optind = 1; while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Check in the command line arglist if(opt == 'n') { val = Option_transformArgument (optarg); Description_setNbVectors (desc, val); } } /* Special argument : nbEvalLib : it must be allocated before dealing with anything else (calling setNbEvalLib () do a lot of allocation stuff) */ optind = 1; while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Check in the command line arglist if(opt == 'E') { Description_parseEvaluationLibraryInput (desc, optarg); } } /* In the end, if anybody defined the nbVector argument, let's define it ourself */ if (Description_getNbVectors (desc) == DEFAULT_NB_VECTORS) { Description_setNbVectors (desc, 1); } return 0; }