18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This application is Copyright 2012 Red Hat, Inc. 38c2ecf20Sopenharmony_ci * Doug Ledford <dledford@redhat.com> 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * mq_perf_tests is free software: you can redistribute it and/or modify 68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 78c2ecf20Sopenharmony_ci * the Free Software Foundation, version 3. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * mq_perf_tests is distributed in the hope that it will be useful, 108c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 118c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 128c2ecf20Sopenharmony_ci * GNU General Public License for more details. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * For the full text of the license, see <http://www.gnu.org/licenses/>. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * mq_perf_tests.c 178c2ecf20Sopenharmony_ci * Tests various types of message queue workloads, concentrating on those 188c2ecf20Sopenharmony_ci * situations that invole large message sizes, large message queue depths, 198c2ecf20Sopenharmony_ci * or both, and reports back useful metrics about kernel message queue 208c2ecf20Sopenharmony_ci * performance. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci#define _GNU_SOURCE 248c2ecf20Sopenharmony_ci#include <stdio.h> 258c2ecf20Sopenharmony_ci#include <stdlib.h> 268c2ecf20Sopenharmony_ci#include <unistd.h> 278c2ecf20Sopenharmony_ci#include <fcntl.h> 288c2ecf20Sopenharmony_ci#include <string.h> 298c2ecf20Sopenharmony_ci#include <limits.h> 308c2ecf20Sopenharmony_ci#include <errno.h> 318c2ecf20Sopenharmony_ci#include <signal.h> 328c2ecf20Sopenharmony_ci#include <pthread.h> 338c2ecf20Sopenharmony_ci#include <sched.h> 348c2ecf20Sopenharmony_ci#include <sys/types.h> 358c2ecf20Sopenharmony_ci#include <sys/time.h> 368c2ecf20Sopenharmony_ci#include <sys/resource.h> 378c2ecf20Sopenharmony_ci#include <sys/stat.h> 388c2ecf20Sopenharmony_ci#include <mqueue.h> 398c2ecf20Sopenharmony_ci#include <popt.h> 408c2ecf20Sopenharmony_ci#include <error.h> 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include "../kselftest.h" 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic char *usage = 458c2ecf20Sopenharmony_ci"Usage:\n" 468c2ecf20Sopenharmony_ci" %s [-c #[,#..] -f] path\n" 478c2ecf20Sopenharmony_ci"\n" 488c2ecf20Sopenharmony_ci" -c # Skip most tests and go straight to a high queue depth test\n" 498c2ecf20Sopenharmony_ci" and then run that test continuously (useful for running at\n" 508c2ecf20Sopenharmony_ci" the same time as some other workload to see how much the\n" 518c2ecf20Sopenharmony_ci" cache thrashing caused by adding messages to a very deep\n" 528c2ecf20Sopenharmony_ci" queue impacts the performance of other programs). The number\n" 538c2ecf20Sopenharmony_ci" indicates which CPU core we should bind the process to during\n" 548c2ecf20Sopenharmony_ci" the run. If you have more than one physical CPU, then you\n" 558c2ecf20Sopenharmony_ci" will need one copy per physical CPU package, and you should\n" 568c2ecf20Sopenharmony_ci" specify the CPU cores to pin ourself to via a comma separated\n" 578c2ecf20Sopenharmony_ci" list of CPU values.\n" 588c2ecf20Sopenharmony_ci" -f Only usable with continuous mode. Pin ourself to the CPUs\n" 598c2ecf20Sopenharmony_ci" as requested, then instead of looping doing a high mq\n" 608c2ecf20Sopenharmony_ci" workload, just busy loop. This will allow us to lock up a\n" 618c2ecf20Sopenharmony_ci" single CPU just like we normally would, but without actually\n" 628c2ecf20Sopenharmony_ci" thrashing the CPU cache. This is to make it easier to get\n" 638c2ecf20Sopenharmony_ci" comparable numbers from some other workload running on the\n" 648c2ecf20Sopenharmony_ci" other CPUs. One set of numbers with # CPUs locked up running\n" 658c2ecf20Sopenharmony_ci" an mq workload, and another set of numbers with those same\n" 668c2ecf20Sopenharmony_ci" CPUs locked away from the test workload, but not doing\n" 678c2ecf20Sopenharmony_ci" anything to trash the cache like the mq workload might.\n" 688c2ecf20Sopenharmony_ci" path Path name of the message queue to create\n" 698c2ecf20Sopenharmony_ci"\n" 708c2ecf20Sopenharmony_ci" Note: this program must be run as root in order to enable all tests\n" 718c2ecf20Sopenharmony_ci"\n"; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cichar *MAX_MSGS = "/proc/sys/fs/mqueue/msg_max"; 748c2ecf20Sopenharmony_cichar *MAX_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_max"; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define min(a, b) ((a) < (b) ? (a) : (b)) 778c2ecf20Sopenharmony_ci#define MAX_CPUS 64 788c2ecf20Sopenharmony_cichar *cpu_option_string; 798c2ecf20Sopenharmony_ciint cpus_to_pin[MAX_CPUS]; 808c2ecf20Sopenharmony_ciint num_cpus_to_pin; 818c2ecf20Sopenharmony_cipthread_t cpu_threads[MAX_CPUS]; 828c2ecf20Sopenharmony_cipthread_t main_thread; 838c2ecf20Sopenharmony_cicpu_set_t *cpu_set; 848c2ecf20Sopenharmony_ciint cpu_set_size; 858c2ecf20Sopenharmony_ciint cpus_online; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define MSG_SIZE 16 888c2ecf20Sopenharmony_ci#define TEST1_LOOPS 10000000 898c2ecf20Sopenharmony_ci#define TEST2_LOOPS 100000 908c2ecf20Sopenharmony_ciint continuous_mode; 918c2ecf20Sopenharmony_ciint continuous_mode_fake; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistruct rlimit saved_limits, cur_limits; 948c2ecf20Sopenharmony_ciint saved_max_msgs, saved_max_msgsize; 958c2ecf20Sopenharmony_ciint cur_max_msgs, cur_max_msgsize; 968c2ecf20Sopenharmony_ciFILE *max_msgs, *max_msgsize; 978c2ecf20Sopenharmony_ciint cur_nice; 988c2ecf20Sopenharmony_cichar *queue_path = "/mq_perf_tests"; 998c2ecf20Sopenharmony_cimqd_t queue = -1; 1008c2ecf20Sopenharmony_cistruct mq_attr result; 1018c2ecf20Sopenharmony_ciint mq_prio_max; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciconst struct poptOption options[] = { 1048c2ecf20Sopenharmony_ci { 1058c2ecf20Sopenharmony_ci .longName = "continuous", 1068c2ecf20Sopenharmony_ci .shortName = 'c', 1078c2ecf20Sopenharmony_ci .argInfo = POPT_ARG_STRING, 1088c2ecf20Sopenharmony_ci .arg = &cpu_option_string, 1098c2ecf20Sopenharmony_ci .val = 'c', 1108c2ecf20Sopenharmony_ci .descrip = "Run continuous tests at a high queue depth in " 1118c2ecf20Sopenharmony_ci "order to test the effects of cache thrashing on " 1128c2ecf20Sopenharmony_ci "other tasks on the system. This test is intended " 1138c2ecf20Sopenharmony_ci "to be run on one core of each physical CPU while " 1148c2ecf20Sopenharmony_ci "some other CPU intensive task is run on all the other " 1158c2ecf20Sopenharmony_ci "cores of that same physical CPU and the other task " 1168c2ecf20Sopenharmony_ci "is timed. It is assumed that the process of adding " 1178c2ecf20Sopenharmony_ci "messages to the message queue in a tight loop will " 1188c2ecf20Sopenharmony_ci "impact that other task to some degree. Once the " 1198c2ecf20Sopenharmony_ci "tests are performed in this way, you should then " 1208c2ecf20Sopenharmony_ci "re-run the tests using fake mode in order to check " 1218c2ecf20Sopenharmony_ci "the difference in time required to perform the CPU " 1228c2ecf20Sopenharmony_ci "intensive task", 1238c2ecf20Sopenharmony_ci .argDescrip = "cpu[,cpu]", 1248c2ecf20Sopenharmony_ci }, 1258c2ecf20Sopenharmony_ci { 1268c2ecf20Sopenharmony_ci .longName = "fake", 1278c2ecf20Sopenharmony_ci .shortName = 'f', 1288c2ecf20Sopenharmony_ci .argInfo = POPT_ARG_NONE, 1298c2ecf20Sopenharmony_ci .arg = &continuous_mode_fake, 1308c2ecf20Sopenharmony_ci .val = 0, 1318c2ecf20Sopenharmony_ci .descrip = "Tie up the CPUs that we would normally tie up in" 1328c2ecf20Sopenharmony_ci "continuous mode, but don't actually do any mq stuff, " 1338c2ecf20Sopenharmony_ci "just keep the CPU busy so it can't be used to process " 1348c2ecf20Sopenharmony_ci "system level tasks as this would free up resources on " 1358c2ecf20Sopenharmony_ci "the other CPU cores and skew the comparison between " 1368c2ecf20Sopenharmony_ci "the no-mqueue work and mqueue work tests", 1378c2ecf20Sopenharmony_ci .argDescrip = NULL, 1388c2ecf20Sopenharmony_ci }, 1398c2ecf20Sopenharmony_ci { 1408c2ecf20Sopenharmony_ci .longName = "path", 1418c2ecf20Sopenharmony_ci .shortName = 'p', 1428c2ecf20Sopenharmony_ci .argInfo = POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, 1438c2ecf20Sopenharmony_ci .arg = &queue_path, 1448c2ecf20Sopenharmony_ci .val = 'p', 1458c2ecf20Sopenharmony_ci .descrip = "The name of the path to use in the mqueue " 1468c2ecf20Sopenharmony_ci "filesystem for our tests", 1478c2ecf20Sopenharmony_ci .argDescrip = "pathname", 1488c2ecf20Sopenharmony_ci }, 1498c2ecf20Sopenharmony_ci POPT_AUTOHELP 1508c2ecf20Sopenharmony_ci POPT_TABLEEND 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic inline void __set(FILE *stream, int value, char *err_msg); 1548c2ecf20Sopenharmony_civoid shutdown(int exit_val, char *err_cause, int line_no); 1558c2ecf20Sopenharmony_civoid sig_action_SIGUSR1(int signum, siginfo_t *info, void *context); 1568c2ecf20Sopenharmony_civoid sig_action(int signum, siginfo_t *info, void *context); 1578c2ecf20Sopenharmony_cistatic inline int get(FILE *stream); 1588c2ecf20Sopenharmony_cistatic inline void set(FILE *stream, int value); 1598c2ecf20Sopenharmony_cistatic inline int try_set(FILE *stream, int value); 1608c2ecf20Sopenharmony_cistatic inline void getr(int type, struct rlimit *rlim); 1618c2ecf20Sopenharmony_cistatic inline void setr(int type, struct rlimit *rlim); 1628c2ecf20Sopenharmony_cistatic inline void open_queue(struct mq_attr *attr); 1638c2ecf20Sopenharmony_civoid increase_limits(void); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic inline void __set(FILE *stream, int value, char *err_msg) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci rewind(stream); 1688c2ecf20Sopenharmony_ci if (fprintf(stream, "%d", value) < 0) 1698c2ecf20Sopenharmony_ci perror(err_msg); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_civoid shutdown(int exit_val, char *err_cause, int line_no) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci static int in_shutdown = 0; 1768c2ecf20Sopenharmony_ci int errno_at_shutdown = errno; 1778c2ecf20Sopenharmony_ci int i; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* In case we get called by multiple threads or from an sighandler */ 1808c2ecf20Sopenharmony_ci if (in_shutdown++) 1818c2ecf20Sopenharmony_ci return; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* Free the cpu_set allocated using CPU_ALLOC in main function */ 1848c2ecf20Sopenharmony_ci CPU_FREE(cpu_set); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci for (i = 0; i < num_cpus_to_pin; i++) 1878c2ecf20Sopenharmony_ci if (cpu_threads[i]) { 1888c2ecf20Sopenharmony_ci pthread_kill(cpu_threads[i], SIGUSR1); 1898c2ecf20Sopenharmony_ci pthread_join(cpu_threads[i], NULL); 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (queue != -1) 1938c2ecf20Sopenharmony_ci if (mq_close(queue)) 1948c2ecf20Sopenharmony_ci perror("mq_close() during shutdown"); 1958c2ecf20Sopenharmony_ci if (queue_path) 1968c2ecf20Sopenharmony_ci /* 1978c2ecf20Sopenharmony_ci * Be silent if this fails, if we cleaned up already it's 1988c2ecf20Sopenharmony_ci * expected to fail 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci mq_unlink(queue_path); 2018c2ecf20Sopenharmony_ci if (saved_max_msgs) 2028c2ecf20Sopenharmony_ci __set(max_msgs, saved_max_msgs, 2038c2ecf20Sopenharmony_ci "failed to restore saved_max_msgs"); 2048c2ecf20Sopenharmony_ci if (saved_max_msgsize) 2058c2ecf20Sopenharmony_ci __set(max_msgsize, saved_max_msgsize, 2068c2ecf20Sopenharmony_ci "failed to restore saved_max_msgsize"); 2078c2ecf20Sopenharmony_ci if (exit_val) 2088c2ecf20Sopenharmony_ci error(exit_val, errno_at_shutdown, "%s at %d", 2098c2ecf20Sopenharmony_ci err_cause, line_no); 2108c2ecf20Sopenharmony_ci exit(0); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_civoid sig_action_SIGUSR1(int signum, siginfo_t *info, void *context) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci if (pthread_self() != main_thread) 2168c2ecf20Sopenharmony_ci pthread_exit(0); 2178c2ecf20Sopenharmony_ci else { 2188c2ecf20Sopenharmony_ci fprintf(stderr, "Caught signal %d in SIGUSR1 handler, " 2198c2ecf20Sopenharmony_ci "exiting\n", signum); 2208c2ecf20Sopenharmony_ci shutdown(0, "", 0); 2218c2ecf20Sopenharmony_ci fprintf(stderr, "\n\nReturned from shutdown?!?!\n\n"); 2228c2ecf20Sopenharmony_ci exit(0); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_civoid sig_action(int signum, siginfo_t *info, void *context) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci if (pthread_self() != main_thread) 2298c2ecf20Sopenharmony_ci pthread_kill(main_thread, signum); 2308c2ecf20Sopenharmony_ci else { 2318c2ecf20Sopenharmony_ci fprintf(stderr, "Caught signal %d, exiting\n", signum); 2328c2ecf20Sopenharmony_ci shutdown(0, "", 0); 2338c2ecf20Sopenharmony_ci fprintf(stderr, "\n\nReturned from shutdown?!?!\n\n"); 2348c2ecf20Sopenharmony_ci exit(0); 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic inline int get(FILE *stream) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci int value; 2418c2ecf20Sopenharmony_ci rewind(stream); 2428c2ecf20Sopenharmony_ci if (fscanf(stream, "%d", &value) != 1) 2438c2ecf20Sopenharmony_ci shutdown(4, "Error reading /proc entry", __LINE__); 2448c2ecf20Sopenharmony_ci return value; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic inline void set(FILE *stream, int value) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci int new_value; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci rewind(stream); 2528c2ecf20Sopenharmony_ci if (fprintf(stream, "%d", value) < 0) 2538c2ecf20Sopenharmony_ci return shutdown(5, "Failed writing to /proc file", __LINE__); 2548c2ecf20Sopenharmony_ci new_value = get(stream); 2558c2ecf20Sopenharmony_ci if (new_value != value) 2568c2ecf20Sopenharmony_ci return shutdown(5, "We didn't get what we wrote to /proc back", 2578c2ecf20Sopenharmony_ci __LINE__); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic inline int try_set(FILE *stream, int value) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci int new_value; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci rewind(stream); 2658c2ecf20Sopenharmony_ci fprintf(stream, "%d", value); 2668c2ecf20Sopenharmony_ci new_value = get(stream); 2678c2ecf20Sopenharmony_ci return new_value == value; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic inline void getr(int type, struct rlimit *rlim) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci if (getrlimit(type, rlim)) 2738c2ecf20Sopenharmony_ci shutdown(6, "getrlimit()", __LINE__); 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic inline void setr(int type, struct rlimit *rlim) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci if (setrlimit(type, rlim)) 2798c2ecf20Sopenharmony_ci shutdown(7, "setrlimit()", __LINE__); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/** 2838c2ecf20Sopenharmony_ci * open_queue - open the global queue for testing 2848c2ecf20Sopenharmony_ci * @attr - An attr struct specifying the desired queue traits 2858c2ecf20Sopenharmony_ci * @result - An attr struct that lists the actual traits the queue has 2868c2ecf20Sopenharmony_ci * 2878c2ecf20Sopenharmony_ci * This open is not allowed to fail, failure will result in an orderly 2888c2ecf20Sopenharmony_ci * shutdown of the program. The global queue_path is used to set what 2898c2ecf20Sopenharmony_ci * queue to open, the queue descriptor is saved in the global queue 2908c2ecf20Sopenharmony_ci * variable. 2918c2ecf20Sopenharmony_ci */ 2928c2ecf20Sopenharmony_cistatic inline void open_queue(struct mq_attr *attr) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci int flags = O_RDWR | O_EXCL | O_CREAT | O_NONBLOCK; 2958c2ecf20Sopenharmony_ci int perms = DEFFILEMODE; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci queue = mq_open(queue_path, flags, perms, attr); 2988c2ecf20Sopenharmony_ci if (queue == -1) 2998c2ecf20Sopenharmony_ci shutdown(1, "mq_open()", __LINE__); 3008c2ecf20Sopenharmony_ci if (mq_getattr(queue, &result)) 3018c2ecf20Sopenharmony_ci shutdown(1, "mq_getattr()", __LINE__); 3028c2ecf20Sopenharmony_ci printf("\n\tQueue %s created:\n", queue_path); 3038c2ecf20Sopenharmony_ci printf("\t\tmq_flags:\t\t\t%s\n", result.mq_flags & O_NONBLOCK ? 3048c2ecf20Sopenharmony_ci "O_NONBLOCK" : "(null)"); 3058c2ecf20Sopenharmony_ci printf("\t\tmq_maxmsg:\t\t\t%lu\n", result.mq_maxmsg); 3068c2ecf20Sopenharmony_ci printf("\t\tmq_msgsize:\t\t\t%lu\n", result.mq_msgsize); 3078c2ecf20Sopenharmony_ci printf("\t\tmq_curmsgs:\t\t\t%lu\n", result.mq_curmsgs); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_civoid *fake_cont_thread(void *arg) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci int i; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci for (i = 0; i < num_cpus_to_pin; i++) 3158c2ecf20Sopenharmony_ci if (cpu_threads[i] == pthread_self()) 3168c2ecf20Sopenharmony_ci break; 3178c2ecf20Sopenharmony_ci printf("\tStarted fake continuous mode thread %d on CPU %d\n", i, 3188c2ecf20Sopenharmony_ci cpus_to_pin[i]); 3198c2ecf20Sopenharmony_ci while (1) 3208c2ecf20Sopenharmony_ci ; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_civoid *cont_thread(void *arg) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci char buff[MSG_SIZE]; 3268c2ecf20Sopenharmony_ci int i, priority; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci for (i = 0; i < num_cpus_to_pin; i++) 3298c2ecf20Sopenharmony_ci if (cpu_threads[i] == pthread_self()) 3308c2ecf20Sopenharmony_ci break; 3318c2ecf20Sopenharmony_ci printf("\tStarted continuous mode thread %d on CPU %d\n", i, 3328c2ecf20Sopenharmony_ci cpus_to_pin[i]); 3338c2ecf20Sopenharmony_ci while (1) { 3348c2ecf20Sopenharmony_ci while (mq_send(queue, buff, sizeof(buff), 0) == 0) 3358c2ecf20Sopenharmony_ci ; 3368c2ecf20Sopenharmony_ci mq_receive(queue, buff, sizeof(buff), &priority); 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci#define drain_queue() \ 3418c2ecf20Sopenharmony_ci while (mq_receive(queue, buff, MSG_SIZE, &prio_in) == MSG_SIZE) 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci#define do_untimed_send() \ 3448c2ecf20Sopenharmony_ci do { \ 3458c2ecf20Sopenharmony_ci if (mq_send(queue, buff, MSG_SIZE, prio_out)) \ 3468c2ecf20Sopenharmony_ci shutdown(3, "Test send failure", __LINE__); \ 3478c2ecf20Sopenharmony_ci } while (0) 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci#define do_send_recv() \ 3508c2ecf20Sopenharmony_ci do { \ 3518c2ecf20Sopenharmony_ci clock_gettime(clock, &start); \ 3528c2ecf20Sopenharmony_ci if (mq_send(queue, buff, MSG_SIZE, prio_out)) \ 3538c2ecf20Sopenharmony_ci shutdown(3, "Test send failure", __LINE__); \ 3548c2ecf20Sopenharmony_ci clock_gettime(clock, &middle); \ 3558c2ecf20Sopenharmony_ci if (mq_receive(queue, buff, MSG_SIZE, &prio_in) != MSG_SIZE) \ 3568c2ecf20Sopenharmony_ci shutdown(3, "Test receive failure", __LINE__); \ 3578c2ecf20Sopenharmony_ci clock_gettime(clock, &end); \ 3588c2ecf20Sopenharmony_ci nsec = ((middle.tv_sec - start.tv_sec) * 1000000000) + \ 3598c2ecf20Sopenharmony_ci (middle.tv_nsec - start.tv_nsec); \ 3608c2ecf20Sopenharmony_ci send_total.tv_nsec += nsec; \ 3618c2ecf20Sopenharmony_ci if (send_total.tv_nsec >= 1000000000) { \ 3628c2ecf20Sopenharmony_ci send_total.tv_sec++; \ 3638c2ecf20Sopenharmony_ci send_total.tv_nsec -= 1000000000; \ 3648c2ecf20Sopenharmony_ci } \ 3658c2ecf20Sopenharmony_ci nsec = ((end.tv_sec - middle.tv_sec) * 1000000000) + \ 3668c2ecf20Sopenharmony_ci (end.tv_nsec - middle.tv_nsec); \ 3678c2ecf20Sopenharmony_ci recv_total.tv_nsec += nsec; \ 3688c2ecf20Sopenharmony_ci if (recv_total.tv_nsec >= 1000000000) { \ 3698c2ecf20Sopenharmony_ci recv_total.tv_sec++; \ 3708c2ecf20Sopenharmony_ci recv_total.tv_nsec -= 1000000000; \ 3718c2ecf20Sopenharmony_ci } \ 3728c2ecf20Sopenharmony_ci } while (0) 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistruct test { 3758c2ecf20Sopenharmony_ci char *desc; 3768c2ecf20Sopenharmony_ci void (*func)(int *); 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_civoid const_prio(int *prio) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci return; 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_civoid inc_prio(int *prio) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci if (++*prio == mq_prio_max) 3878c2ecf20Sopenharmony_ci *prio = 0; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_civoid dec_prio(int *prio) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci if (--*prio < 0) 3938c2ecf20Sopenharmony_ci *prio = mq_prio_max - 1; 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_civoid random_prio(int *prio) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci *prio = random() % mq_prio_max; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistruct test test2[] = { 4028c2ecf20Sopenharmony_ci {"\n\tTest #2a: Time send/recv message, queue full, constant prio\n", 4038c2ecf20Sopenharmony_ci const_prio}, 4048c2ecf20Sopenharmony_ci {"\n\tTest #2b: Time send/recv message, queue full, increasing prio\n", 4058c2ecf20Sopenharmony_ci inc_prio}, 4068c2ecf20Sopenharmony_ci {"\n\tTest #2c: Time send/recv message, queue full, decreasing prio\n", 4078c2ecf20Sopenharmony_ci dec_prio}, 4088c2ecf20Sopenharmony_ci {"\n\tTest #2d: Time send/recv message, queue full, random prio\n", 4098c2ecf20Sopenharmony_ci random_prio}, 4108c2ecf20Sopenharmony_ci {NULL, NULL} 4118c2ecf20Sopenharmony_ci}; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci/** 4148c2ecf20Sopenharmony_ci * Tests to perform (all done with MSG_SIZE messages): 4158c2ecf20Sopenharmony_ci * 4168c2ecf20Sopenharmony_ci * 1) Time to add/remove message with 0 messages on queue 4178c2ecf20Sopenharmony_ci * 1a) with constant prio 4188c2ecf20Sopenharmony_ci * 2) Time to add/remove message when queue close to capacity: 4198c2ecf20Sopenharmony_ci * 2a) with constant prio 4208c2ecf20Sopenharmony_ci * 2b) with increasing prio 4218c2ecf20Sopenharmony_ci * 2c) with decreasing prio 4228c2ecf20Sopenharmony_ci * 2d) with random prio 4238c2ecf20Sopenharmony_ci * 3) Test limits of priorities honored (double check _SC_MQ_PRIO_MAX) 4248c2ecf20Sopenharmony_ci */ 4258c2ecf20Sopenharmony_civoid *perf_test_thread(void *arg) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci char buff[MSG_SIZE]; 4288c2ecf20Sopenharmony_ci int prio_out, prio_in; 4298c2ecf20Sopenharmony_ci int i; 4308c2ecf20Sopenharmony_ci clockid_t clock; 4318c2ecf20Sopenharmony_ci pthread_t *t; 4328c2ecf20Sopenharmony_ci struct timespec res, start, middle, end, send_total, recv_total; 4338c2ecf20Sopenharmony_ci unsigned long long nsec; 4348c2ecf20Sopenharmony_ci struct test *cur_test; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci t = &cpu_threads[0]; 4378c2ecf20Sopenharmony_ci printf("\n\tStarted mqueue performance test thread on CPU %d\n", 4388c2ecf20Sopenharmony_ci cpus_to_pin[0]); 4398c2ecf20Sopenharmony_ci mq_prio_max = sysconf(_SC_MQ_PRIO_MAX); 4408c2ecf20Sopenharmony_ci if (mq_prio_max == -1) 4418c2ecf20Sopenharmony_ci shutdown(2, "sysconf(_SC_MQ_PRIO_MAX)", __LINE__); 4428c2ecf20Sopenharmony_ci if (pthread_getcpuclockid(cpu_threads[0], &clock) != 0) 4438c2ecf20Sopenharmony_ci shutdown(2, "pthread_getcpuclockid", __LINE__); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (clock_getres(clock, &res)) 4468c2ecf20Sopenharmony_ci shutdown(2, "clock_getres()", __LINE__); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci printf("\t\tMax priorities:\t\t\t%d\n", mq_prio_max); 4498c2ecf20Sopenharmony_ci printf("\t\tClock resolution:\t\t%lu nsec%s\n", res.tv_nsec, 4508c2ecf20Sopenharmony_ci res.tv_nsec > 1 ? "s" : ""); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci printf("\n\tTest #1: Time send/recv message, queue empty\n"); 4558c2ecf20Sopenharmony_ci printf("\t\t(%d iterations)\n", TEST1_LOOPS); 4568c2ecf20Sopenharmony_ci prio_out = 0; 4578c2ecf20Sopenharmony_ci send_total.tv_sec = 0; 4588c2ecf20Sopenharmony_ci send_total.tv_nsec = 0; 4598c2ecf20Sopenharmony_ci recv_total.tv_sec = 0; 4608c2ecf20Sopenharmony_ci recv_total.tv_nsec = 0; 4618c2ecf20Sopenharmony_ci for (i = 0; i < TEST1_LOOPS; i++) 4628c2ecf20Sopenharmony_ci do_send_recv(); 4638c2ecf20Sopenharmony_ci printf("\t\tSend msg:\t\t\t%ld.%lus total time\n", 4648c2ecf20Sopenharmony_ci send_total.tv_sec, send_total.tv_nsec); 4658c2ecf20Sopenharmony_ci nsec = ((unsigned long long)send_total.tv_sec * 1000000000 + 4668c2ecf20Sopenharmony_ci send_total.tv_nsec) / TEST1_LOOPS; 4678c2ecf20Sopenharmony_ci printf("\t\t\t\t\t\t%lld nsec/msg\n", nsec); 4688c2ecf20Sopenharmony_ci printf("\t\tRecv msg:\t\t\t%ld.%lus total time\n", 4698c2ecf20Sopenharmony_ci recv_total.tv_sec, recv_total.tv_nsec); 4708c2ecf20Sopenharmony_ci nsec = ((unsigned long long)recv_total.tv_sec * 1000000000 + 4718c2ecf20Sopenharmony_ci recv_total.tv_nsec) / TEST1_LOOPS; 4728c2ecf20Sopenharmony_ci printf("\t\t\t\t\t\t%lld nsec/msg\n", nsec); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci for (cur_test = test2; cur_test->desc != NULL; cur_test++) { 4768c2ecf20Sopenharmony_ci printf("%s:\n", cur_test->desc); 4778c2ecf20Sopenharmony_ci printf("\t\t(%d iterations)\n", TEST2_LOOPS); 4788c2ecf20Sopenharmony_ci prio_out = 0; 4798c2ecf20Sopenharmony_ci send_total.tv_sec = 0; 4808c2ecf20Sopenharmony_ci send_total.tv_nsec = 0; 4818c2ecf20Sopenharmony_ci recv_total.tv_sec = 0; 4828c2ecf20Sopenharmony_ci recv_total.tv_nsec = 0; 4838c2ecf20Sopenharmony_ci printf("\t\tFilling queue..."); 4848c2ecf20Sopenharmony_ci fflush(stdout); 4858c2ecf20Sopenharmony_ci clock_gettime(clock, &start); 4868c2ecf20Sopenharmony_ci for (i = 0; i < result.mq_maxmsg - 1; i++) { 4878c2ecf20Sopenharmony_ci do_untimed_send(); 4888c2ecf20Sopenharmony_ci cur_test->func(&prio_out); 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci clock_gettime(clock, &end); 4918c2ecf20Sopenharmony_ci nsec = ((unsigned long long)(end.tv_sec - start.tv_sec) * 4928c2ecf20Sopenharmony_ci 1000000000) + (end.tv_nsec - start.tv_nsec); 4938c2ecf20Sopenharmony_ci printf("done.\t\t%lld.%llds\n", nsec / 1000000000, 4948c2ecf20Sopenharmony_ci nsec % 1000000000); 4958c2ecf20Sopenharmony_ci printf("\t\tTesting..."); 4968c2ecf20Sopenharmony_ci fflush(stdout); 4978c2ecf20Sopenharmony_ci for (i = 0; i < TEST2_LOOPS; i++) { 4988c2ecf20Sopenharmony_ci do_send_recv(); 4998c2ecf20Sopenharmony_ci cur_test->func(&prio_out); 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci printf("done.\n"); 5028c2ecf20Sopenharmony_ci printf("\t\tSend msg:\t\t\t%ld.%lus total time\n", 5038c2ecf20Sopenharmony_ci send_total.tv_sec, send_total.tv_nsec); 5048c2ecf20Sopenharmony_ci nsec = ((unsigned long long)send_total.tv_sec * 1000000000 + 5058c2ecf20Sopenharmony_ci send_total.tv_nsec) / TEST2_LOOPS; 5068c2ecf20Sopenharmony_ci printf("\t\t\t\t\t\t%lld nsec/msg\n", nsec); 5078c2ecf20Sopenharmony_ci printf("\t\tRecv msg:\t\t\t%ld.%lus total time\n", 5088c2ecf20Sopenharmony_ci recv_total.tv_sec, recv_total.tv_nsec); 5098c2ecf20Sopenharmony_ci nsec = ((unsigned long long)recv_total.tv_sec * 1000000000 + 5108c2ecf20Sopenharmony_ci recv_total.tv_nsec) / TEST2_LOOPS; 5118c2ecf20Sopenharmony_ci printf("\t\t\t\t\t\t%lld nsec/msg\n", nsec); 5128c2ecf20Sopenharmony_ci printf("\t\tDraining queue..."); 5138c2ecf20Sopenharmony_ci fflush(stdout); 5148c2ecf20Sopenharmony_ci clock_gettime(clock, &start); 5158c2ecf20Sopenharmony_ci drain_queue(); 5168c2ecf20Sopenharmony_ci clock_gettime(clock, &end); 5178c2ecf20Sopenharmony_ci nsec = ((unsigned long long)(end.tv_sec - start.tv_sec) * 5188c2ecf20Sopenharmony_ci 1000000000) + (end.tv_nsec - start.tv_nsec); 5198c2ecf20Sopenharmony_ci printf("done.\t\t%lld.%llds\n", nsec / 1000000000, 5208c2ecf20Sopenharmony_ci nsec % 1000000000); 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci return 0; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_civoid increase_limits(void) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci cur_limits.rlim_cur = RLIM_INFINITY; 5288c2ecf20Sopenharmony_ci cur_limits.rlim_max = RLIM_INFINITY; 5298c2ecf20Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 5308c2ecf20Sopenharmony_ci while (try_set(max_msgs, cur_max_msgs += 10)) 5318c2ecf20Sopenharmony_ci ; 5328c2ecf20Sopenharmony_ci cur_max_msgs = get(max_msgs); 5338c2ecf20Sopenharmony_ci while (try_set(max_msgsize, cur_max_msgsize += 1024)) 5348c2ecf20Sopenharmony_ci ; 5358c2ecf20Sopenharmony_ci cur_max_msgsize = get(max_msgsize); 5368c2ecf20Sopenharmony_ci if (setpriority(PRIO_PROCESS, 0, -20) != 0) 5378c2ecf20Sopenharmony_ci shutdown(2, "setpriority()", __LINE__); 5388c2ecf20Sopenharmony_ci cur_nice = -20; 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct mq_attr attr; 5448c2ecf20Sopenharmony_ci char *option, *next_option; 5458c2ecf20Sopenharmony_ci int i, cpu, rc; 5468c2ecf20Sopenharmony_ci struct sigaction sa; 5478c2ecf20Sopenharmony_ci poptContext popt_context; 5488c2ecf20Sopenharmony_ci void *retval; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci main_thread = pthread_self(); 5518c2ecf20Sopenharmony_ci num_cpus_to_pin = 0; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci if (sysconf(_SC_NPROCESSORS_ONLN) == -1) { 5548c2ecf20Sopenharmony_ci perror("sysconf(_SC_NPROCESSORS_ONLN)"); 5558c2ecf20Sopenharmony_ci exit(1); 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (getuid() != 0) 5598c2ecf20Sopenharmony_ci ksft_exit_skip("Not running as root, but almost all tests " 5608c2ecf20Sopenharmony_ci "require root in order to modify\nsystem settings. " 5618c2ecf20Sopenharmony_ci "Exiting.\n"); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci cpus_online = min(MAX_CPUS, sysconf(_SC_NPROCESSORS_ONLN)); 5648c2ecf20Sopenharmony_ci cpu_set = CPU_ALLOC(cpus_online); 5658c2ecf20Sopenharmony_ci if (cpu_set == NULL) { 5668c2ecf20Sopenharmony_ci perror("CPU_ALLOC()"); 5678c2ecf20Sopenharmony_ci exit(1); 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci cpu_set_size = CPU_ALLOC_SIZE(cpus_online); 5708c2ecf20Sopenharmony_ci CPU_ZERO_S(cpu_set_size, cpu_set); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci popt_context = poptGetContext(NULL, argc, (const char **)argv, 5738c2ecf20Sopenharmony_ci options, 0); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci while ((rc = poptGetNextOpt(popt_context)) > 0) { 5768c2ecf20Sopenharmony_ci switch (rc) { 5778c2ecf20Sopenharmony_ci case 'c': 5788c2ecf20Sopenharmony_ci continuous_mode = 1; 5798c2ecf20Sopenharmony_ci option = cpu_option_string; 5808c2ecf20Sopenharmony_ci do { 5818c2ecf20Sopenharmony_ci next_option = strchr(option, ','); 5828c2ecf20Sopenharmony_ci if (next_option) 5838c2ecf20Sopenharmony_ci *next_option = '\0'; 5848c2ecf20Sopenharmony_ci cpu = atoi(option); 5858c2ecf20Sopenharmony_ci if (cpu >= cpus_online) 5868c2ecf20Sopenharmony_ci fprintf(stderr, "CPU %d exceeds " 5878c2ecf20Sopenharmony_ci "cpus online, ignoring.\n", 5888c2ecf20Sopenharmony_ci cpu); 5898c2ecf20Sopenharmony_ci else 5908c2ecf20Sopenharmony_ci cpus_to_pin[num_cpus_to_pin++] = cpu; 5918c2ecf20Sopenharmony_ci if (next_option) 5928c2ecf20Sopenharmony_ci option = ++next_option; 5938c2ecf20Sopenharmony_ci } while (next_option && num_cpus_to_pin < MAX_CPUS); 5948c2ecf20Sopenharmony_ci /* Double check that they didn't give us the same CPU 5958c2ecf20Sopenharmony_ci * more than once */ 5968c2ecf20Sopenharmony_ci for (cpu = 0; cpu < num_cpus_to_pin; cpu++) { 5978c2ecf20Sopenharmony_ci if (CPU_ISSET_S(cpus_to_pin[cpu], cpu_set_size, 5988c2ecf20Sopenharmony_ci cpu_set)) { 5998c2ecf20Sopenharmony_ci fprintf(stderr, "Any given CPU may " 6008c2ecf20Sopenharmony_ci "only be given once.\n"); 6018c2ecf20Sopenharmony_ci goto err_code; 6028c2ecf20Sopenharmony_ci } else 6038c2ecf20Sopenharmony_ci CPU_SET_S(cpus_to_pin[cpu], 6048c2ecf20Sopenharmony_ci cpu_set_size, cpu_set); 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci break; 6078c2ecf20Sopenharmony_ci case 'p': 6088c2ecf20Sopenharmony_ci /* 6098c2ecf20Sopenharmony_ci * Although we can create a msg queue with a 6108c2ecf20Sopenharmony_ci * non-absolute path name, unlink will fail. So, 6118c2ecf20Sopenharmony_ci * if the name doesn't start with a /, add one 6128c2ecf20Sopenharmony_ci * when we save it. 6138c2ecf20Sopenharmony_ci */ 6148c2ecf20Sopenharmony_ci option = queue_path; 6158c2ecf20Sopenharmony_ci if (*option != '/') { 6168c2ecf20Sopenharmony_ci queue_path = malloc(strlen(option) + 2); 6178c2ecf20Sopenharmony_ci if (!queue_path) { 6188c2ecf20Sopenharmony_ci perror("malloc()"); 6198c2ecf20Sopenharmony_ci goto err_code; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci queue_path[0] = '/'; 6228c2ecf20Sopenharmony_ci queue_path[1] = 0; 6238c2ecf20Sopenharmony_ci strcat(queue_path, option); 6248c2ecf20Sopenharmony_ci free(option); 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci if (continuous_mode && num_cpus_to_pin == 0) { 6318c2ecf20Sopenharmony_ci fprintf(stderr, "Must pass at least one CPU to continuous " 6328c2ecf20Sopenharmony_ci "mode.\n"); 6338c2ecf20Sopenharmony_ci poptPrintUsage(popt_context, stderr, 0); 6348c2ecf20Sopenharmony_ci goto err_code; 6358c2ecf20Sopenharmony_ci } else if (!continuous_mode) { 6368c2ecf20Sopenharmony_ci num_cpus_to_pin = 1; 6378c2ecf20Sopenharmony_ci cpus_to_pin[0] = cpus_online - 1; 6388c2ecf20Sopenharmony_ci } 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci max_msgs = fopen(MAX_MSGS, "r+"); 6418c2ecf20Sopenharmony_ci max_msgsize = fopen(MAX_MSGSIZE, "r+"); 6428c2ecf20Sopenharmony_ci if (!max_msgs) 6438c2ecf20Sopenharmony_ci shutdown(2, "Failed to open msg_max", __LINE__); 6448c2ecf20Sopenharmony_ci if (!max_msgsize) 6458c2ecf20Sopenharmony_ci shutdown(2, "Failed to open msgsize_max", __LINE__); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* Load up the current system values for everything we can */ 6488c2ecf20Sopenharmony_ci getr(RLIMIT_MSGQUEUE, &saved_limits); 6498c2ecf20Sopenharmony_ci cur_limits = saved_limits; 6508c2ecf20Sopenharmony_ci saved_max_msgs = cur_max_msgs = get(max_msgs); 6518c2ecf20Sopenharmony_ci saved_max_msgsize = cur_max_msgsize = get(max_msgsize); 6528c2ecf20Sopenharmony_ci errno = 0; 6538c2ecf20Sopenharmony_ci cur_nice = getpriority(PRIO_PROCESS, 0); 6548c2ecf20Sopenharmony_ci if (errno) 6558c2ecf20Sopenharmony_ci shutdown(2, "getpriority()", __LINE__); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* Tell the user our initial state */ 6588c2ecf20Sopenharmony_ci printf("\nInitial system state:\n"); 6598c2ecf20Sopenharmony_ci printf("\tUsing queue path:\t\t\t%s\n", queue_path); 6608c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t\t%ld\n", 6618c2ecf20Sopenharmony_ci (long) saved_limits.rlim_cur); 6628c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t\t%ld\n", 6638c2ecf20Sopenharmony_ci (long) saved_limits.rlim_max); 6648c2ecf20Sopenharmony_ci printf("\tMaximum Message Size:\t\t\t%d\n", saved_max_msgsize); 6658c2ecf20Sopenharmony_ci printf("\tMaximum Queue Size:\t\t\t%d\n", saved_max_msgs); 6668c2ecf20Sopenharmony_ci printf("\tNice value:\t\t\t\t%d\n", cur_nice); 6678c2ecf20Sopenharmony_ci printf("\n"); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci increase_limits(); 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci printf("Adjusted system state for testing:\n"); 6728c2ecf20Sopenharmony_ci if (cur_limits.rlim_cur == RLIM_INFINITY) { 6738c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t\t(unlimited)\n"); 6748c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t\t(unlimited)\n"); 6758c2ecf20Sopenharmony_ci } else { 6768c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t\t%ld\n", 6778c2ecf20Sopenharmony_ci (long) cur_limits.rlim_cur); 6788c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t\t%ld\n", 6798c2ecf20Sopenharmony_ci (long) cur_limits.rlim_max); 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci printf("\tMaximum Message Size:\t\t\t%d\n", cur_max_msgsize); 6828c2ecf20Sopenharmony_ci printf("\tMaximum Queue Size:\t\t\t%d\n", cur_max_msgs); 6838c2ecf20Sopenharmony_ci printf("\tNice value:\t\t\t\t%d\n", cur_nice); 6848c2ecf20Sopenharmony_ci printf("\tContinuous mode:\t\t\t(%s)\n", continuous_mode ? 6858c2ecf20Sopenharmony_ci (continuous_mode_fake ? "fake mode" : "enabled") : 6868c2ecf20Sopenharmony_ci "disabled"); 6878c2ecf20Sopenharmony_ci printf("\tCPUs to pin:\t\t\t\t%d", cpus_to_pin[0]); 6888c2ecf20Sopenharmony_ci for (cpu = 1; cpu < num_cpus_to_pin; cpu++) 6898c2ecf20Sopenharmony_ci printf(",%d", cpus_to_pin[cpu]); 6908c2ecf20Sopenharmony_ci printf("\n"); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci sa.sa_sigaction = sig_action_SIGUSR1; 6938c2ecf20Sopenharmony_ci sigemptyset(&sa.sa_mask); 6948c2ecf20Sopenharmony_ci sigaddset(&sa.sa_mask, SIGHUP); 6958c2ecf20Sopenharmony_ci sigaddset(&sa.sa_mask, SIGINT); 6968c2ecf20Sopenharmony_ci sigaddset(&sa.sa_mask, SIGQUIT); 6978c2ecf20Sopenharmony_ci sigaddset(&sa.sa_mask, SIGTERM); 6988c2ecf20Sopenharmony_ci sa.sa_flags = SA_SIGINFO; 6998c2ecf20Sopenharmony_ci if (sigaction(SIGUSR1, &sa, NULL) == -1) 7008c2ecf20Sopenharmony_ci shutdown(1, "sigaction(SIGUSR1)", __LINE__); 7018c2ecf20Sopenharmony_ci sa.sa_sigaction = sig_action; 7028c2ecf20Sopenharmony_ci if (sigaction(SIGHUP, &sa, NULL) == -1) 7038c2ecf20Sopenharmony_ci shutdown(1, "sigaction(SIGHUP)", __LINE__); 7048c2ecf20Sopenharmony_ci if (sigaction(SIGINT, &sa, NULL) == -1) 7058c2ecf20Sopenharmony_ci shutdown(1, "sigaction(SIGINT)", __LINE__); 7068c2ecf20Sopenharmony_ci if (sigaction(SIGQUIT, &sa, NULL) == -1) 7078c2ecf20Sopenharmony_ci shutdown(1, "sigaction(SIGQUIT)", __LINE__); 7088c2ecf20Sopenharmony_ci if (sigaction(SIGTERM, &sa, NULL) == -1) 7098c2ecf20Sopenharmony_ci shutdown(1, "sigaction(SIGTERM)", __LINE__); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci if (!continuous_mode_fake) { 7128c2ecf20Sopenharmony_ci attr.mq_flags = O_NONBLOCK; 7138c2ecf20Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs; 7148c2ecf20Sopenharmony_ci attr.mq_msgsize = MSG_SIZE; 7158c2ecf20Sopenharmony_ci open_queue(&attr); 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci for (i = 0; i < num_cpus_to_pin; i++) { 7188c2ecf20Sopenharmony_ci pthread_attr_t thread_attr; 7198c2ecf20Sopenharmony_ci void *thread_func; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci if (continuous_mode_fake) 7228c2ecf20Sopenharmony_ci thread_func = &fake_cont_thread; 7238c2ecf20Sopenharmony_ci else if (continuous_mode) 7248c2ecf20Sopenharmony_ci thread_func = &cont_thread; 7258c2ecf20Sopenharmony_ci else 7268c2ecf20Sopenharmony_ci thread_func = &perf_test_thread; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci CPU_ZERO_S(cpu_set_size, cpu_set); 7298c2ecf20Sopenharmony_ci CPU_SET_S(cpus_to_pin[i], cpu_set_size, cpu_set); 7308c2ecf20Sopenharmony_ci pthread_attr_init(&thread_attr); 7318c2ecf20Sopenharmony_ci pthread_attr_setaffinity_np(&thread_attr, cpu_set_size, 7328c2ecf20Sopenharmony_ci cpu_set); 7338c2ecf20Sopenharmony_ci if (pthread_create(&cpu_threads[i], &thread_attr, thread_func, 7348c2ecf20Sopenharmony_ci NULL)) 7358c2ecf20Sopenharmony_ci shutdown(1, "pthread_create()", __LINE__); 7368c2ecf20Sopenharmony_ci pthread_attr_destroy(&thread_attr); 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci if (!continuous_mode) { 7408c2ecf20Sopenharmony_ci pthread_join(cpu_threads[0], &retval); 7418c2ecf20Sopenharmony_ci shutdown((long)retval, "perf_test_thread()", __LINE__); 7428c2ecf20Sopenharmony_ci } else { 7438c2ecf20Sopenharmony_ci while (1) 7448c2ecf20Sopenharmony_ci sleep(1); 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci shutdown(0, "", 0); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_cierr_code: 7498c2ecf20Sopenharmony_ci CPU_FREE(cpu_set); 7508c2ecf20Sopenharmony_ci exit(1); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci} 753