X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..f427ee49d309d8fc33ebf3042c3a775f2f530ded:/tools/tests/MPMMTest/MPMMtest.c?ds=sidebyside diff --git a/tools/tests/MPMMTest/MPMMtest.c b/tools/tests/MPMMTest/MPMMtest.c index c2991c37c..09401d502 100644 --- a/tools/tests/MPMMTest/MPMMtest.c +++ b/tools/tests/MPMMTest/MPMMtest.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,8 @@ #include #include #include +#include +#include "../unit_tests/tests_common.h" /* for record_perf_data() */ #include @@ -24,21 +27,21 @@ typedef struct { - mach_msg_header_t header; - mach_msg_trailer_t trailer; // subtract this when sending + mach_msg_header_t header; + mach_msg_trailer_t trailer; // subtract this when sending } ipc_trivial_message; typedef struct { - mach_msg_header_t header; - u_int32_t numbers[0]; - mach_msg_trailer_t trailer; // subtract this when sending + mach_msg_header_t header; + u_int32_t numbers[0]; + mach_msg_trailer_t trailer; // subtract this when sending } ipc_inline_message; typedef struct { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_ool_descriptor_t descriptor; - mach_msg_trailer_t trailer; // subtract this when sending + mach_msg_header_t header; + mach_msg_body_t body; + mach_msg_ool_descriptor_t descriptor; + mach_msg_trailer_t trailer; // subtract this when sending } ipc_complex_message; enum { @@ -61,51 +64,58 @@ struct port_args { }; typedef union { - pid_t pid; - pthread_t tid; + pid_t pid; + pthread_t tid; } thread_id_t; /* Global options */ -static int verbose = 0; -static boolean_t affinity = FALSE; -static boolean_t timeshare = FALSE; -static boolean_t threaded = FALSE; -static boolean_t oneway = FALSE; -static boolean_t useset = FALSE; -int msg_type; -int num_ints; -int num_msgs; -int num_clients; -int num_servers; -int client_delay; -int client_spin; -int client_pages; -int portcount = 1; -int setcount = 0; -boolean_t stress_prepost = FALSE; -char **server_port_name; - -struct port_args *server_port_args; +static int verbose = 0; +static boolean_t affinity = FALSE; +static boolean_t timeshare = FALSE; +static boolean_t threaded = FALSE; +static boolean_t oneway = FALSE; +static boolean_t useset = FALSE; +static boolean_t save_perfdata = FALSE; +int msg_type; +int num_ints; +int num_msgs; +int num_clients; +int num_servers; +int client_delay; +int client_spin; +int client_pages; +int portcount = 1; +int setcount = 0; +boolean_t stress_prepost = FALSE; +char **server_port_name; + +struct port_args *server_port_args; /* global data */ mach_timebase_info_data_t g_timebase; int64_t g_client_send_time = 0; -static inline uint64_t ns_to_abs(uint64_t ns) +static inline uint64_t +ns_to_abs(uint64_t ns) { return ns * g_timebase.denom / g_timebase.numer; } -static inline uint64_t abs_to_ns(uint64_t abs) +static inline uint64_t +abs_to_ns(uint64_t abs) { return abs * g_timebase.numer / g_timebase.denom; } -void signal_handler(int sig) { +void +signal_handler(int sig) +{ } -void usage(const char *progname) { +void +usage(const char *progname) +{ fprintf(stderr, "usage: %s [options]\n", progname); fprintf(stderr, "where options are:\n"); fprintf(stderr, " -affinity\t\tthreads use affinity\n"); @@ -114,6 +124,7 @@ void usage(const char *progname) { fprintf(stderr, " -verbose\t\tbe verbose (use multiple times to increase verbosity)\n"); fprintf(stderr, " -oneway\t\tdo not request return reply\n"); fprintf(stderr, " -count num\t\tnumber of messages to send\n"); + fprintf(stderr, " -perf \t\tCreate perfdata files for metrics.\n"); fprintf(stderr, " -type trivial|inline|complex\ttype of messages to send\n"); fprintf(stderr, " -numints num\tnumber of 32-bit ints to send in messages\n"); fprintf(stderr, " -servers num\tnumber of server threads to run\n"); @@ -141,10 +152,12 @@ void usage(const char *progname) { exit(1); } -void parse_args(int argc, char *argv[]) { - host_basic_info_data_t info; - mach_msg_type_number_t count; - kern_return_t result; +void +parse_args(int argc, char *argv[]) +{ + host_basic_info_data_t info; + mach_msg_type_number_t count; + kern_return_t result; /* Initialize defaults */ msg_type = msg_type_trivial; @@ -154,12 +167,13 @@ void parse_args(int argc, char *argv[]) { num_clients = 4; count = HOST_BASIC_INFO_COUNT; - result = host_info(mach_host_self(), HOST_BASIC_INFO, - (host_info_t)&info, &count); - if (result == KERN_SUCCESS && info.avail_cpus > 1) + result = host_info(mach_host_self(), HOST_BASIC_INFO, + (host_info_t)&info, &count); + if (result == KERN_SUCCESS && info.avail_cpus > 1) { num_servers = info.avail_cpus / 2; - else + } else { num_servers = 1; + } const char *progname = argv[0]; argc--; argv++; @@ -179,60 +193,74 @@ void parse_args(int argc, char *argv[]) { } else if (0 == strcmp("-oneway", argv[0])) { oneway = TRUE; argc--; argv++; + } else if (0 == strcmp("-perf", argv[0])) { + save_perfdata = TRUE; + argc--; argv++; } else if (0 == strcmp("-type", argv[0])) { - if (argc < 2) + if (argc < 2) { usage(progname); + } if (0 == strcmp("trivial", argv[1])) { msg_type = msg_type_trivial; } else if (0 == strcmp("inline", argv[1])) { msg_type = msg_type_inline; } else if (0 == strcmp("complex", argv[1])) { msg_type = msg_type_complex; - } else + } else { usage(progname); + } argc -= 2; argv += 2; } else if (0 == strcmp("-numints", argv[0])) { - if (argc < 2) + if (argc < 2) { usage(progname); + } num_ints = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; } else if (0 == strcmp("-count", argv[0])) { - if (argc < 2) + if (argc < 2) { usage(progname); + } num_msgs = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; - } else if (0 == strcmp("-clients", argv[0])) { - if (argc < 2) + } else if (0 == strcmp("-clients", argv[0])) { + if (argc < 2) { usage(progname); + } num_clients = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; - } else if (0 == strcmp("-servers", argv[0])) { - if (argc < 2) + } else if (0 == strcmp("-servers", argv[0])) { + if (argc < 2) { usage(progname); + } num_servers = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; } else if (0 == strcmp("-delay", argv[0])) { - if (argc < 2) + if (argc < 2) { usage(progname); + } client_delay = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; } else if (0 == strcmp("-spin", argv[0])) { - if (argc < 2) + if (argc < 2) { usage(progname); + } client_spin = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; } else if (0 == strcmp("-pages", argv[0])) { - if (argc < 2) + if (argc < 2) { usage(progname); + } client_pages = strtoul(argv[1], NULL, 0); argc -= 2; argv += 2; } else if (0 == strcmp("-set", argv[0])) { - if (argc < 3) + if (argc < 3) { usage(progname); + } setcount = strtoul(argv[1], NULL, 0); portcount = strtoul(argv[2], NULL, 0); - if (setcount <= 0 || portcount <= 0) + if (setcount <= 0 || portcount <= 0) { usage(progname); + } useset = TRUE; argc -= 3; argv += 3; } else if (0 == strcmp("-prepost", argv[0])) { @@ -257,17 +285,18 @@ void parse_args(int argc, char *argv[]) { } } -void setup_server_ports(struct port_args *ports) +void +setup_server_ports(struct port_args *ports) { kern_return_t ret = 0; mach_port_t bsport; mach_port_t port; - ports->req_size = MAX(sizeof(ipc_inline_message) + - sizeof(u_int32_t) * num_ints, - sizeof(ipc_complex_message)); - ports->reply_size = sizeof(ipc_trivial_message) - - sizeof(mach_msg_trailer_t); + ports->req_size = MAX(sizeof(ipc_inline_message) + + sizeof(u_int32_t) * num_ints, + sizeof(ipc_complex_message)); + ports->reply_size = sizeof(ipc_trivial_message) - + sizeof(mach_msg_trailer_t); ports->req_msg = malloc(ports->req_size); ports->reply_msg = malloc(ports->reply_size); if (setcount > 0) { @@ -294,15 +323,16 @@ void setup_server_ports(struct port_args *ports) for (int ns = 0; ns < setcount; ns++) { ret = mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_PORT_SET, - &ports->set[ns]); + MACH_PORT_RIGHT_PORT_SET, + &ports->set[ns]); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(SET): ", ret); exit(1); } - if (verbose > 1) + if (verbose > 1) { printf("SVR[%d] allocated set[%d] %#x\n", - ports->server_num, ns, ports->set[ns]); + ports->server_num, ns, ports->set[ns]); + } set = ports->set[ns]; } @@ -313,25 +343,27 @@ void setup_server_ports(struct port_args *ports) /* stuff the portset(s) with ports */ for (int i = 0; i < portcount; i++) { - ret = mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - &port); + ret = mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, + &port); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(PORT): ", ret); exit(1); } - if (stress_prepost) + if (stress_prepost) { ports->port_list[i] = port; + } if (useset) { /* insert the port into _all_ allocated lowest-level sets */ for (int ns = 0; ns < setcount; ns++) { - if (verbose > 1) + if (verbose > 1) { printf("SVR[%d] moving port %#x into set %#x...\n", - ports->server_num, port, ports->set[ns]); + ports->server_num, port, ports->set[ns]); + } ret = mach_port_insert_member(mach_task_self(), - port, ports->set[ns]); + port, ports->set[ns]); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_member(): ", ret); exit(1); @@ -347,9 +379,9 @@ void setup_server_ports(struct port_args *ports) /* insert a send right for _each_ port */ for (int i = 0; i < portcount; i++) { ret = mach_port_insert_right(mach_task_self(), - ports->port_list[i], - ports->port_list[i], - MACH_MSG_TYPE_MAKE_SEND); + ports->port_list[i], + ports->port_list[i], + MACH_MSG_TYPE_MAKE_SEND); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_right(): ", ret); exit(1); @@ -357,9 +389,9 @@ void setup_server_ports(struct port_args *ports) } } else { ret = mach_port_insert_right(mach_task_self(), - ports->port, - ports->port, - MACH_MSG_TYPE_MAKE_SEND); + ports->port, + ports->port, + MACH_MSG_TYPE_MAKE_SEND); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_right(): ", ret); exit(1); @@ -374,80 +406,84 @@ void setup_server_ports(struct port_args *ports) if (verbose) { printf("server waiting for IPC messages from client on port '%s' (%#x).\n", - server_port_name[ports->server_num], ports->port); + server_port_name[ports->server_num], ports->port); } ret = bootstrap_register(bsport, - server_port_name[ports->server_num], - ports->port); + server_port_name[ports->server_num], + ports->port); if (KERN_SUCCESS != ret) { mach_error("bootstrap_register(): ", ret); exit(1); } } -void setup_client_ports(struct port_args *ports) +void +setup_client_ports(struct port_args *ports) { kern_return_t ret = 0; - switch(msg_type) { - case msg_type_trivial: - ports->req_size = sizeof(ipc_trivial_message); - break; - case msg_type_inline: - ports->req_size = sizeof(ipc_inline_message) + - sizeof(u_int32_t) * num_ints; - break; - case msg_type_complex: - ports->req_size = sizeof(ipc_complex_message); - break; + switch (msg_type) { + case msg_type_trivial: + ports->req_size = sizeof(ipc_trivial_message); + break; + case msg_type_inline: + ports->req_size = sizeof(ipc_inline_message) + + sizeof(u_int32_t) * num_ints; + break; + case msg_type_complex: + ports->req_size = sizeof(ipc_complex_message); + break; } ports->req_size -= sizeof(mach_msg_trailer_t); ports->reply_size = sizeof(ipc_trivial_message); ports->req_msg = malloc(ports->req_size); ports->reply_msg = malloc(ports->reply_size); - ret = mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - &(ports->port)); + ret = mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, + &(ports->port)); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(): ", ret); exit(1); } if (verbose) { printf("Client sending %d %s IPC messages to port '%s' in %s mode\n", - num_msgs, (msg_type == msg_type_inline) ? - "inline" : ((msg_type == msg_type_complex) ? - "complex" : "trivial"), - server_port_name[ports->server_num], - (oneway ? "oneway" : "rpc")); + num_msgs, (msg_type == msg_type_inline) ? + "inline" : ((msg_type == msg_type_complex) ? + "complex" : "trivial"), + server_port_name[ports->server_num], + (oneway ? "oneway" : "rpc")); } } static void -thread_setup(int tag) { - kern_return_t ret; - thread_extended_policy_data_t epolicy; - thread_affinity_policy_data_t policy; +thread_setup(int tag) +{ + kern_return_t ret; + thread_extended_policy_data_t epolicy; + thread_affinity_policy_data_t policy; if (!timeshare) { epolicy.timeshare = FALSE; ret = thread_policy_set( - mach_thread_self(), THREAD_EXTENDED_POLICY, - (thread_policy_t) &epolicy, - THREAD_EXTENDED_POLICY_COUNT); - if (ret != KERN_SUCCESS) + mach_thread_self(), THREAD_EXTENDED_POLICY, + (thread_policy_t) &epolicy, + THREAD_EXTENDED_POLICY_COUNT); + if (ret != KERN_SUCCESS) { printf("thread_policy_set(THREAD_EXTENDED_POLICY) returned %d\n", ret); + } } - if (affinity) { - policy.affinity_tag = tag; - ret = thread_policy_set( - mach_thread_self(), THREAD_AFFINITY_POLICY, - (thread_policy_t) &policy, - THREAD_AFFINITY_POLICY_COUNT); - if (ret != KERN_SUCCESS) - printf("thread_policy_set(THREAD_AFFINITY_POLICY) returned %d\n", ret); - } + if (affinity) { + policy.affinity_tag = tag; + ret = thread_policy_set( + mach_thread_self(), THREAD_AFFINITY_POLICY, + (thread_policy_t) &policy, + THREAD_AFFINITY_POLICY_COUNT); + if (ret != KERN_SUCCESS) { + printf("thread_policy_set(THREAD_AFFINITY_POLICY) returned %d\n", ret); + } + } } void * @@ -470,46 +506,51 @@ server(void *serverarg) recv_port = (useset) ? args->rcv_set : args->port; for (idx = 0; idx < totalmsg; idx++) { - if (verbose > 2) + if (verbose > 2) { printf("server awaiting message %d\n", idx); + } ret = mach_msg(args->req_msg, - MACH_RCV_MSG|MACH_RCV_INTERRUPT|MACH_RCV_LARGE, - 0, - args->req_size, - recv_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - if (MACH_RCV_INTERRUPTED == ret) + MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_LARGE, + 0, + args->req_size, + recv_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + if (MACH_RCV_INTERRUPTED == ret) { break; + } if (MACH_MSG_SUCCESS != ret) { - if (verbose) + if (verbose) { printf("mach_msg() ret=%d", ret); + } mach_error("mach_msg (receive): ", ret); exit(1); } - if (verbose > 2) + if (verbose > 2) { printf("server received message %d\n", idx); + } if (args->req_msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) { - ret = vm_deallocate(mach_task_self(), - (vm_address_t)((ipc_complex_message *)args->req_msg)->descriptor.address, - ((ipc_complex_message *)args->req_msg)->descriptor.size); + ret = vm_deallocate(mach_task_self(), + (vm_address_t)((ipc_complex_message *)args->req_msg)->descriptor.address, + ((ipc_complex_message *)args->req_msg)->descriptor.size); } if (1 == args->req_msg->msgh_id) { - if (verbose > 2) + if (verbose > 2) { printf("server sending reply %d\n", idx); + } args->reply_msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); args->reply_msg->msgh_size = args->reply_size; args->reply_msg->msgh_remote_port = args->req_msg->msgh_remote_port; args->reply_msg->msgh_local_port = MACH_PORT_NULL; args->reply_msg->msgh_id = 2; ret = mach_msg(args->reply_msg, - MACH_SEND_MSG, - args->reply_size, - 0, - MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); + MACH_SEND_MSG, + args->reply_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); if (MACH_MSG_SUCCESS != ret) { mach_error("mach_msg (send): ", ret); exit(1); @@ -517,11 +558,13 @@ server(void *serverarg) } } - if (!useset) + if (!useset) { return NULL; + } - if (verbose < 1) + if (verbose < 1) { return NULL; + } uint64_t deltans = 0; /* @@ -529,8 +572,9 @@ server(void *serverarg) * and measure the time. */ for (int ns = 0; ns < setcount; ns++) { - if (verbose > 1) + if (verbose > 1) { printf("\tTearing down set[%d] %#x...\n", ns, args->set[ns]); + } starttm = mach_absolute_time(); ret = mach_port_mod_refs(mach_task_self(), args->set[ns], MACH_PORT_RIGHT_PORT_SET, -1); endtm = mach_absolute_time(); @@ -550,34 +594,36 @@ server(void *serverarg) } static inline void -client_spin_loop(unsigned count, void (fn)(void)) +client_spin_loop(unsigned count, void(fn)(void)) { - while (count--) + while (count--) { fn(); + } } -static long dummy_memory; -static long *client_memory = &dummy_memory; +static long dummy_memory; +static long *client_memory = &dummy_memory; static void client_work_atom(void) { - static int i; + static int i; - if (++i > client_pages * PAGE_SIZE / sizeof(long)) + if (++i > client_pages * PAGE_SIZE / sizeof(long)) { i = 0; + } client_memory[i] = 0; } -static int calibration_count = 10000; -static int calibration_usec; +static int calibration_count = 10000; +static int calibration_usec; static void * calibrate_client_work(void) { - long dummy; - struct timeval nowtv; - struct timeval warmuptv = { 0, 100 * 1000 }; /* 100ms */ - struct timeval starttv; - struct timeval endtv; + long dummy; + struct timeval nowtv; + struct timeval warmuptv = { 0, 100 * 1000 }; /* 100ms */ + struct timeval starttv; + struct timeval endtv; if (client_spin) { /* Warm-up the stepper first... */ @@ -586,8 +632,8 @@ calibrate_client_work(void) do { client_spin_loop(calibration_count, client_work_atom); gettimeofday(&nowtv, NULL); - } while (timercmp(&nowtv, &endtv, < )); - + } while (timercmp(&nowtv, &endtv, < )); + /* Now do the calibration */ while (TRUE) { gettimeofday(&starttv, NULL); @@ -608,9 +654,10 @@ calibrate_client_work(void) calibration_count /= calibration_usec; break; } - if (verbose > 1) + if (verbose > 1) { printf("calibration_count=%d calibration_usec=%d\n", - calibration_count, calibration_usec); + calibration_count, calibration_usec); + } } return NULL; } @@ -618,38 +665,40 @@ calibrate_client_work(void) static void * client_work(void) { - if (client_spin) { - client_spin_loop(calibration_count*client_spin, - client_work_atom); + client_spin_loop(calibration_count * client_spin, + client_work_atom); } - + if (client_delay) { usleep(client_delay); } return NULL; } -void *client(void *threadarg) +void * +client(void *threadarg) { struct port_args args; struct port_args *svr_args = NULL; int idx; - mach_msg_header_t *req, *reply; + mach_msg_header_t *req, *reply; mach_port_t bsport, servport; kern_return_t ret; int server_num = (int)(uintptr_t)threadarg; void *ints = malloc(sizeof(u_int32_t) * num_ints); - if (verbose) + if (verbose) { printf("client(%d) started, server port name %s\n", - server_num, server_port_name[server_num]); + server_num, server_port_name[server_num]); + } args.server_num = server_num; thread_setup(server_num + 1); - if (stress_prepost) + if (stress_prepost) { svr_args = &server_port_args[server_num]; + } /* find server port */ ret = task_get_bootstrap_port(mach_task_self(), &bsport); @@ -658,8 +707,8 @@ void *client(void *threadarg) exit(1); } ret = bootstrap_look_up(bsport, - server_port_name[server_num], - &servport); + server_port_name[server_num], + &servport); if (KERN_SUCCESS != ret) { mach_error("bootstrap_look_up(): ", ret); exit(1); @@ -669,14 +718,15 @@ void *client(void *threadarg) /* Allocate and touch memory */ if (client_pages) { - unsigned i; + unsigned i; client_memory = (long *) malloc(client_pages * PAGE_SIZE); - for (i = 0; i < client_pages; i++) + for (i = 0; i < client_pages; i++) { client_memory[i * PAGE_SIZE / sizeof(long)] = 0; + } } uint64_t starttm, endtm; - + /* start message loop */ for (idx = 0; idx < num_msgs; idx++) { req = args.req_msg; @@ -693,7 +743,7 @@ void *client(void *threadarg) req->msgh_local_port = MACH_PORT_NULL; } else { req->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, - MACH_MSG_TYPE_MAKE_SEND_ONCE); + MACH_MSG_TYPE_MAKE_SEND_ONCE); req->msgh_local_port = args.port; } req->msgh_id = oneway ? 0 : 1; @@ -701,23 +751,24 @@ void *client(void *threadarg) (req)->msgh_bits |= MACH_MSGH_BITS_COMPLEX; ((ipc_complex_message *)req)->body.msgh_descriptor_count = 1; ((ipc_complex_message *)req)->descriptor.address = ints; - ((ipc_complex_message *)req)->descriptor.size = - num_ints * sizeof(u_int32_t); + ((ipc_complex_message *)req)->descriptor.size = + num_ints * sizeof(u_int32_t); ((ipc_complex_message *)req)->descriptor.deallocate = FALSE; ((ipc_complex_message *)req)->descriptor.copy = MACH_MSG_VIRTUAL_COPY; ((ipc_complex_message *)req)->descriptor.type = MACH_MSG_OOL_DESCRIPTOR; } - if (verbose > 2) + if (verbose > 2) { printf("client sending message %d to port %#x\n", - idx, req->msgh_remote_port); + idx, req->msgh_remote_port); + } starttm = mach_absolute_time(); - ret = mach_msg(req, - MACH_SEND_MSG, - args.req_size, - 0, - MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); + ret = mach_msg(req, + MACH_SEND_MSG, + args.req_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); endtm = mach_absolute_time(); if (MACH_MSG_SUCCESS != ret) { mach_error("mach_msg (send): ", ret); @@ -725,30 +776,33 @@ void *client(void *threadarg) exit(1); break; } - if (stress_prepost) + if (stress_prepost) { OSAtomicAdd64(endtm - starttm, &g_client_send_time); + } if (!oneway) { - if (verbose > 2) + if (verbose > 2) { printf("client awaiting reply %d\n", idx); + } reply->msgh_bits = 0; reply->msgh_size = args.reply_size; reply->msgh_local_port = args.port; - ret = mach_msg(args.reply_msg, - MACH_RCV_MSG|MACH_RCV_INTERRUPT, - 0, - args.reply_size, - args.port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); + ret = mach_msg(args.reply_msg, + MACH_RCV_MSG | MACH_RCV_INTERRUPT, + 0, + args.reply_size, + args.port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); if (MACH_MSG_SUCCESS != ret) { mach_error("mach_msg (receive): ", ret); fprintf(stderr, "bailing after %u iterations\n", - idx); + idx); exit(1); } - if (verbose > 2) + if (verbose > 2) { printf("client received reply %d\n", idx); + } } client_work(); @@ -759,44 +813,53 @@ void *client(void *threadarg) } static void -thread_spawn(thread_id_t *thread, void *(fn)(void *), void *arg) { +thread_spawn(thread_id_t *thread, void *(fn)(void *), void *arg) +{ if (threaded) { - kern_return_t ret; + kern_return_t ret; ret = pthread_create( - &thread->tid, - NULL, - fn, - arg); - if (ret != 0) + &thread->tid, + NULL, + fn, + arg); + if (ret != 0) { err(1, "pthread_create()"); - if (verbose > 1) + } + if (verbose > 1) { printf("created pthread %p\n", thread->tid); + } } else { thread->pid = fork(); if (thread->pid == 0) { - if (verbose > 1) + if (verbose > 1) { printf("calling %p(%p)\n", fn, arg); + } fn(arg); exit(0); } - if (verbose > 1) + if (verbose > 1) { printf("forked pid %d\n", thread->pid); + } } } static void -thread_join(thread_id_t *thread) { +thread_join(thread_id_t *thread) +{ if (threaded) { - kern_return_t ret; - if (verbose > 1) + kern_return_t ret; + if (verbose > 1) { printf("joining thread %p\n", thread->tid); + } ret = pthread_join(thread->tid, NULL); - if (ret != KERN_SUCCESS) + if (ret != KERN_SUCCESS) { err(1, "pthread_join(%p)", thread->tid); + } } else { - int stat; - if (verbose > 1) + int stat; + if (verbose > 1) { printf("waiting for pid %d\n", thread->pid); + } waitpid(thread->pid, &stat, 0); } } @@ -804,10 +867,10 @@ thread_join(thread_id_t *thread) { static void wait_for_servers(void) { - int i; - int retry_count = 10; - mach_port_t bsport, servport; - kern_return_t ret; + int i; + int retry_count = 10; + mach_port_t bsport, servport; + kern_return_t ret; /* find server port */ ret = task_get_bootstrap_port(mach_task_self(), &bsport); @@ -819,26 +882,28 @@ wait_for_servers(void) while (retry_count-- > 0) { for (i = 0; i < num_servers; i++) { ret = bootstrap_look_up(bsport, - server_port_name[i], - &servport); + server_port_name[i], + &servport); if (ret != KERN_SUCCESS) { break; } } - if (ret == KERN_SUCCESS) + if (ret == KERN_SUCCESS) { return; - usleep(100 * 1000); /* 100ms */ + } + usleep(100 * 1000); /* 100ms */ } fprintf(stderr, "Server(s) failed to register\n"); exit(1); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - int i; - int j; - thread_id_t *client_id; - thread_id_t *server_id; + int i; + int j; + thread_id_t *client_id; + thread_id_t *server_id; signal(SIGINT, signal_handler); parse_args(argc, argv); @@ -854,8 +919,9 @@ int main(int argc, char *argv[]) * If we're using affinity create an empty namespace now * so this is shared by all our offspring. */ - if (affinity) + if (affinity) { thread_setup(0); + } server_id = (thread_id_t *) malloc(num_servers * sizeof(thread_id_t)); server_port_name = (char **) malloc(num_servers * sizeof(char *)); @@ -865,8 +931,9 @@ int main(int argc, char *argv[]) exit(1); } - if (verbose) + if (verbose) { printf("creating %d servers\n", num_servers); + } for (i = 0; i < num_servers; i++) { server_port_name[i] = (char *) malloc(sizeof("PORT.pppppp.xx")); /* PORT names include pid of main process for disambiguation */ @@ -883,12 +950,12 @@ int main(int argc, char *argv[]) * the clients and the clock. */ wait_for_servers(); - - printf("%d server%s, %d client%s per server (%d total) %u messages...", - num_servers, (num_servers > 1)? "s" : "", - num_clients, (num_clients > 1)? "s" : "", - totalclients, - totalmsg); + + printf("%d server%s, %d client%s per server (%d total) %u messages...", + num_servers, (num_servers > 1)? "s" : "", + num_clients, (num_clients > 1)? "s" : "", + totalclients, + totalmsg); fflush(stdout); /* Call gettimeofday() once and throw away result; some implementations @@ -898,12 +965,13 @@ int main(int argc, char *argv[]) gettimeofday(&starttv, NULL); client_id = (thread_id_t *) malloc(totalclients * sizeof(thread_id_t)); - if (verbose) + if (verbose) { printf("creating %d clients\n", totalclients); + } for (i = 0; i < num_servers; i++) { for (j = 0; j < num_clients; j++) { thread_spawn( - &client_id[(i*num_clients) + j], + &client_id[(i * num_clients) + j], client, (void *) (long) i); } @@ -915,8 +983,9 @@ int main(int argc, char *argv[]) } gettimeofday(&endtv, NULL); - if (verbose) + if (verbose) { printf("all servers complete: waiting for clients...\n"); + } for (i = 0; i < totalclients; i++) { thread_join(&client_id[i]); @@ -930,24 +999,33 @@ int main(int argc, char *argv[]) deltatv.tv_usec += 1000000; } - double dsecs = (double) deltatv.tv_sec + - 1.0E-6 * (double) deltatv.tv_usec; + double dsecs = (double) deltatv.tv_sec + + 1.0E-6 * (double) deltatv.tv_usec; printf(" in %lu.%03u seconds\n", - deltatv.tv_sec, deltatv.tv_usec/1000); + deltatv.tv_sec, deltatv.tv_usec / 1000); printf(" throughput in messages/sec: %g\n", - (double)totalmsg / dsecs); - printf(" average message latency (usec): %2.3g\n", - dsecs * 1.0E6 / (double) totalmsg); + (double)totalmsg / dsecs); + printf(" average message latency (usec): %2.3g\n", + dsecs * 1.0E6 / (double) totalmsg); + + double time_in_sec = (double)deltatv.tv_sec + (double)deltatv.tv_usec / 1000.0; + double throughput_msg_p_sec = (double) totalmsg / dsecs; + double avg_msg_latency = dsecs * 1.0E6 / (double)totalmsg; + + if (save_perfdata == TRUE) { + char name[256]; + snprintf(name, sizeof(name), "%s_avg_msg_latency", basename(argv[0])); + record_perf_data(name, "usec", avg_msg_latency, "Message latency measured in microseconds. Lower is better", stderr); + } if (stress_prepost) { int64_t sendns = abs_to_ns(g_client_send_time); dsecs = (double)sendns / (double)NSEC_PER_SEC; printf(" total send time: %2.3gs\n", dsecs); printf(" average send time (usec): %2.3g\n", - dsecs * 1.0E6 / (double)totalmsg); + dsecs * 1.0E6 / (double)totalmsg); } - return (0); - + return 0; }