Example #1
0
void *
server(void *serverarg)
{
	int idx;
	kern_return_t ret;
	int totalmsg = num_msgs * num_clients;
	mach_port_t recv_port;
	uint64_t starttm, endtm;

	int svr_num = (int)(uintptr_t)serverarg;
	struct port_args *args = &server_port_args[svr_num];

	args->server_num = svr_num;
	setup_server_ports(args);

	thread_setup(args->server_num + 1);

	recv_port = (useset) ? args->rcv_set : args->port;

	for (idx = 0; idx < totalmsg; idx++) {
		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)
			break;
		if (MACH_MSG_SUCCESS != ret) {
			if (verbose)
				printf("mach_msg() ret=%d", ret);
			mach_error("mach_msg (receive): ", ret);
			exit(1);
		}
		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);
		}

		if (1 == args->req_msg->msgh_id) {
			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);
			if (MACH_MSG_SUCCESS != ret) {
				mach_error("mach_msg (send): ", ret);
				exit(1);
			}
		}
	}

	if (!useset)
		return NULL;

	if (verbose < 1)
		return NULL;

	uint64_t deltans = 0;
	/*
	 * If we're using multiple sets, explicitly tear them all down
	 * and measure the time.
	 */
	for (int ns = 0; ns < setcount; ns++) {
		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();
		deltans += abs_to_ns(endtm - starttm);
		if (ret != KERN_SUCCESS) {
			mach_error("mach_port_mod_refs(): ", ret);
			exit(1);
		}
	}

	uint64_t nlinks = (uint64_t)setcount * (uint64_t)portcount;

	printf("\tteardown of %llu links took %llu ns\n", nlinks, deltans);
	printf("\t%lluns per set\n", deltans / (uint64_t)setcount);

	return NULL;
}
Example #2
0
void *
server(void *serverarg) 
{
	int kq;
	struct kevent64_s kev[1];
	int err;
	struct port_args args;
	int idx;
	kern_return_t ret;
	int totalmsg = num_msgs * num_clients;

	args.server_num = (int) (long) serverarg;
	setup_server_ports(&args);

	thread_setup(args.server_num + 1);
	
	kq = kqueue();
	if (kq == -1) {
		perror("kqueue");
		exit(1);
	}
	EV_SET64(&kev[0], args.pset, EVFILT_MACHPORT, (EV_ADD | EV_CLEAR | EV_DISPATCH), 
#if DIRECT_MSG_RCV
		 MACH_RCV_MSG|MACH_RCV_LARGE, 0, 0, (mach_vm_address_t)args.req_msg, args.req_size);
#else
		0, 0, 0, 0, 0);
#endif
	err = kevent64(kq, kev, 1, NULL, 0, 0, NULL);
	if (err == -1) {
		perror("kevent");
		exit(1);
	}
	for (idx = 0; idx < totalmsg; idx++) {

		if (verbose) 
			printf("server awaiting message %d\n", idx);
	retry:
		EV_SET64(&kev[0], args.pset, EVFILT_MACHPORT, EV_ENABLE, 
#if DIRECT_MSG_RCV
			 MACH_RCV_MSG|MACH_RCV_LARGE, 0, 0, (mach_vm_address_t)args.req_msg, args.req_size);
#else
			0, 0, 0, 0, 0);
#endif
		err = kevent64(kq, kev, 1, kev, 1, 0, NULL);
		if (err == -1) {
			perror("kevent64");
			exit(1);
		}		
		if (err == 0) {
		  // printf("kevent64: returned zero\n");
			goto retry;
		}

#if DIRECT_MSG_RCV
		ret = kev[0].fflags;
		if (MACH_MSG_SUCCESS != ret) {
			if (verbose)
				printf("kevent64() mach_msg_return=%d", ret);
			mach_error("kevent64 (msg receive): ", ret);
			exit(1);
		} 
#else
		if (kev[0].data != args.port)
			printf("kevent64(MACH_PORT_NULL) port name (0x%x) != expected (0x%x)\n", kev[0].data, args.port);

		args.req_msg->msgh_bits = 0;
		args.req_msg->msgh_size = args.req_size;
		args.req_msg->msgh_local_port = args.port;
		ret = mach_msg(args.req_msg,  
				MACH_RCV_MSG|MACH_RCV_INTERRUPT|MACH_RCV_LARGE, 
				0, 
				args.req_size,  
				args.pset, 
				MACH_MSG_TIMEOUT_NONE, 
				MACH_PORT_NULL);
		if (MACH_RCV_INTERRUPTED == ret)
			break;
		if (MACH_MSG_SUCCESS != ret) {
			if (verbose)
				printf("mach_msg() ret=%d", ret);
			mach_error("mach_msg (receive): ", ret);
			exit(1);
		}
#endif
		if (verbose)
			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);
		}

		if (1 == args.req_msg->msgh_id) {
			if (verbose) 
				printf("server sending reply %d\n", idx);
			args.reply_msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,  
					MACH_MSG_TYPE_MAKE_SEND);
			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 = args.req_msg->msgh_local_port;
			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);
			if (MACH_MSG_SUCCESS != ret) {
				mach_error("mach_msg (send): ", ret);
				exit(1);
			}
		}
	}
}