void *client(void *threadarg) { struct port_args args; struct port_args *svr_args = NULL; int idx; 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) printf("client(%d) started, server port name %s\n", server_num, server_port_name[server_num]); args.server_num = server_num; thread_setup(server_num + 1); if (stress_prepost) svr_args = &server_port_args[server_num]; /* find server port */ ret = task_get_bootstrap_port(mach_task_self(), &bsport); if (KERN_SUCCESS != ret) { mach_error("task_get_bootstrap_port(): ", ret); exit(1); } ret = bootstrap_look_up(bsport, server_port_name[server_num], &servport); if (KERN_SUCCESS != ret) { mach_error("bootstrap_look_up(): ", ret); exit(1); } setup_client_ports(&args); /* Allocate and touch memory */ if (client_pages) { unsigned i; client_memory = (long *) malloc(client_pages * PAGE_SIZE); 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; reply = args.reply_msg; req->msgh_size = args.req_size; if (stress_prepost) { req->msgh_remote_port = svr_args->port_list[idx % portcount]; } else { req->msgh_remote_port = servport; } if (oneway) { req->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); 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); req->msgh_local_port = args.port; } req->msgh_id = oneway ? 0 : 1; if (msg_type == msg_type_complex) { (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.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) printf("client sending message %d to port %#x\n", 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); endtm = mach_absolute_time(); if (MACH_MSG_SUCCESS != ret) { mach_error("mach_msg (send): ", ret); fprintf(stderr, "bailing after %u iterations\n", idx); exit(1); break; } if (stress_prepost) OSAtomicAdd64(endtm - starttm, &g_client_send_time); if (!oneway) { 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); if (MACH_MSG_SUCCESS != ret) { mach_error("mach_msg (receive): ", ret); fprintf(stderr, "bailing after %u iterations\n", idx); exit(1); } if (verbose > 2) printf("client received reply %d\n", idx); } client_work(); } free(ints); return NULL; }
template <typename T> static T add(volatile T* scalar, T other) { return (T)OSAtomicAdd64((int64)other, (int64*)scalar); }