Beispiel #1
0
void thread0_lib_init(void)
{
	memset(&thread0_info, 0, sizeof(thread0_info));
	/* we don't care about the message, so don't bother with a UCQ */
	sysc_evq = get_eventq(EV_MBOX_BITMAP);
	sysc_evq->ev_flags = EVENT_INDIR | EVENT_WAKEUP;
	register_ev_handler(EV_SYSCALL, thread0_handle_syscall, 0);
}
Beispiel #2
0
/* Called from uthread_slim_init() */
void init_posix_signals(void)
{
	struct event_queue *posix_sig_ev_q;
	register_ev_handler(EV_POSIX_SIGNAL, handle_event, 0);
	posix_sig_ev_q = get_eventq(EV_MBOX_UCQ);
	assert(posix_sig_ev_q);
	posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
	                           EVENT_WAKEUP;
	register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
	wfl_init(&sigdata_list);
}
Beispiel #3
0
/* to trick uthread_create() */
int main(int argc, char** argv)
{
	uint32_t vcoreid;
	int retval;

	/* Initialize our barrier. */
	mcs_barrier_init(&b, max_vcores());

	/* vcore_context test */
	assert(!in_vcore_context());
	
	/* prep indirect ev_q.  Note we grab a big one */
	indirect_q = get_eventq(EV_MBOX_UCQ);
	indirect_q->ev_flags = EVENT_IPI;
	indirect_q->ev_vcore = 1;			/* IPI core 1 */
	indirect_q->ev_handler = 0;
	printf("Registering %08p for event type %d\n", indirect_q,
	       EV_FREE_APPLE_PIE);
	register_kevent_q(indirect_q, EV_FREE_APPLE_PIE);

	/* handle events: just want to print out what we get.  This is just a
	 * quick set of handlers, not a registration for a kevent. */
	for (int i = 0; i < MAX_NR_EVENT; i++)
		register_ev_handler(i, handle_generic, 0);
	/* Want to use the default ev_ev (which we just overwrote) */
	register_ev_handler(EV_EVENT, handle_ev_ev, 0);
	/* vcore_lib_init() done in vcore_request() now. */
	/* Set up event reception.  For example, this will allow us to receive an
	 * event and IPI for USER_IPIs on vcore 0.  Check event.c for more stuff.
	 * Note you don't have to register for USER_IPIs to receive ones you send
	 * yourself with sys_self_notify(). */
	enable_kevent(EV_USER_IPI, 0, EVENT_IPI | EVENT_VCORE_PRIVATE);
	/* Receive pending preemption events.  (though there's no PP handler) */
	struct event_queue *ev_q = get_eventq_vcpd(0, EVENT_VCORE_PRIVATE);
	ev_q->ev_flags = EVENT_IPI | EVENT_VCORE_APPRO;
	register_kevent_q(ev_q, EV_PREEMPT_PENDING);
	/* We also receive preemption events, it is set up in uthread.c */

	/* Inits a thread for us, though we won't use it.  Just a hack to get into
	 * _M mode.  Note this requests one vcore for us */
	struct uthread dummy = {0};
	uthread_2ls_init(&dummy, &ghetto_sched_ops);
	uthread_mcp_init();
	/* Reset the blockon to be the spinner...  This is really shitty.  Any
	 * blocking calls after we become an MCP and before this will fail.  This is
	 * just mhello showing its warts due to trying to work outside uthread.c */
	ros_syscall_blockon = __ros_syscall_spinon;

	if ((vcoreid = vcore_id())) {
		printf("Should never see me! (from vcore %d)\n", vcoreid);
	} else { // core 0
		temp = 0xdeadbeef;
		printf("Hello from vcore %d with temp addr = %p and temp = %p\n",
		       vcoreid, &temp, temp);
		printf("Multi-Goodbye, world, from PID: %d!\n", sys_getpid());
		printf("Requesting %d vcores\n", max_vcores() - 1);
		retval = vcore_request(max_vcores() - 1); /* since we already have 1 */
		//retval = vcore_request(5);
		printf("This is vcore0, right after vcore_request, retval=%d\n", retval);
		/* vcore_context test */
		assert(!in_vcore_context());
	}

	//#if 0
	/* test notifying my vcore2 */
	udelay(5000000);
	printf("Vcore 0 self-notifying vcore 2 with notif 4!\n");
	struct event_msg msg;
	msg.ev_type = 4;
	sys_self_notify(2, 4, &msg, TRUE);
	udelay(5000000);
	printf("Vcore 0 notifying itself with notif 6!\n");
	msg.ev_type = 6;
	sys_notify(sys_getpid(), 6, &msg);
	udelay(1000000);
	//#endif

	/* test loop for restarting a uthread_ctx */
	if (vcoreid == 0) {
		int ctr = 0;
		while(1) {
			printf("Vcore %d Spinning (%d), temp = %08x!\n", vcoreid, ctr++, temp);
			udelay(5000000);
			//exit(0);
		}
	}

	printf("Vcore %d Done!\n", vcoreid);
	//mcs_barrier_wait(&b,vcore_id());

	printf("All Cores Done!\n", vcoreid);
	while(1); // manually kill from the monitor
	/* since everyone should cleanup their uthreads, even if they don't plan on
	 * calling their code or want uthreads in the first place. <3 */
	uthread_cleanup(&dummy);
	return 0;
}
Beispiel #4
0
int main(int argc, char** argv)
{
	int num_started, retval;
	unsigned int ev_type;

	/* register our syscall handler (2LS does this) */
	register_ev_handler(EV_SYSCALL, handle_syscall, 0);

	printf("Trying to block\n");
	/* Not doing anything else to it: no EVENT_IPI yet, etc. */
	ev_q = get_eventq();
	/* issue the diagnostic block syscall */
	sysc.num = SYS_block;
	sysc.arg0 = 5000;	/* 5ms */
	sysc.ev_q = ev_q;
	/* Trap */
	num_started = __ros_arch_syscall((long)&sysc, 1);
	if (!(atomic_read(&sysc.flags) & SC_DONE))
		printf("Not done, looping!\n");
	/* You could poll on this.  This is really ghetto, but i got rid of
	 * event_activity, whose sole purpose was to encourage spinning. */
	while (!(atomic_read(&sysc.flags) & SC_DONE))
		cpu_relax();
	handle_event_q(ev_q);
	/* by now, we should have run our handler */
	/********************************************************/
	/* Start MCP / IPI test */
	printf("Switching to _M mode and testing an IPI-d ev_q\n");
	printf("Our indirect ev_q is %08p\n", ev_q);

/* begin: stuff userspace needs to do before switching to multi-mode */
	/* Note we don't need to set up event reception for any particular kevent.
	 * The ev_q in the syscall said to send an IPI to vcore 0 which means an
	 * EV_EVENT will be sent straight to vcore0. */
	/* Inits a thread for us, though we won't use it.  Just a hack to get into
	 * _M mode.  Note this requests one vcore for us */
	struct uthread dummy = {0};
	uthread_2ls_init(&dummy, &ghetto_sched_ops);
	uthread_mcs_init();
	/* Need to save our floating point state somewhere (like in the
	 * user_thread_tcb so it can be restarted too */
	enable_notifs(0);
/* end: stuff userspace needs to do before switching to multi-mode */

	retval = vcore_request(1);
	if (retval < 0)
		printf("No cores granted, Rut Ro Raggy!\n");
	/* now we're back in thread 0 on vcore 0 */
	ev_q->ev_flags = EVENT_IPI;
	ev_q->ev_vcore = 0;
	sysc.u_data = (void*)1;	/* using this to loop on */
	/* issue the diagnostic blocking syscall */
	sysc.num = SYS_block;
	sysc.arg0 = 5000;	/* 5ms */
	sysc.ev_q = ev_q;
	num_started = __ros_arch_syscall((long)&sysc, 1);
	/* have this thread "wait" */
	if (!(atomic_read(&sysc.flags) & SC_DONE))
		printf("Not done, looping on a local variable!\n");
	while (sysc.u_data)
		cpu_relax();
	assert(atomic_read(&sysc.flags) & SC_DONE);
	printf("Syscall unblocked, IPI broke me out of the loop.\n");

	/* done */
	put_eventq(ev_q);
	printf("Syscall test exiting\n");
	return 0;
}
Beispiel #5
0
int main(int argc, char **argv)
{
	int ctlfd, timerfd, alarm_nr, ret, srvfd;
	char buf[20];
	char path[32];
	struct event_queue *ev_q;

	printf("Starting alarm test\n");
	/* standard 9ns stuff: clone and read it to get our path, ending up with the
	 * ctlfd and timerfd for #A/aN/{ctl,timer}.  if you plan to fork, you can
	 * open CLOEXEC. */
	ctlfd = open("#A/clone", O_RDWR | O_CLOEXEC);
	if (ctlfd < 0) {
		perror("Can't clone an alarm");
		exit(-1);
	}
	ret = read(ctlfd, buf, sizeof(buf) - 1);
	if (ret <= 0) {
		if (!ret)
			printf("Got early EOF from ctl\n");
		else
			perror("Can't read ctl");
		exit(-1);
	}
	buf[ret] = 0;
	snprintf(path, sizeof(path), "#A/a%s/timer", buf);
	/* Don't open CLOEXEC if you want to post it to srv later */
	timerfd = open(path, O_RDWR);
	if (timerfd < 0) {
		perror("Can't open timer");
		exit(-1);
	}
	/* Since we're doing SPAM_PUBLIC later, we actually don't need a big ev_q.
	 * But someone might copy/paste this and change a flag. */
	register_ev_handler(EV_ALARM, handle_alarm, 0);
	if (!(ev_q = get_big_event_q())) {
		perror("Failed ev_q");	/* it'll actually PF if malloc fails */
		exit(-1);
	}
	ev_q->ev_vcore = 0;
	/* I think this is all the flags we need; gotta write that dissertation
	 * chapter (and event how-to)!  We may get more than one event per alarm, if
	 * we have concurrent preempts/yields. */
	ev_q->ev_flags = EVENT_IPI | EVENT_SPAM_PUBLIC;
	/* Register the ev_q for our alarm */
	ret = snprintf(path, sizeof(path), "evq %llx", ev_q);
	ret = write(ctlfd, path, ret);
	if (ret <= 0) {
		perror("Failed to write ev_q");
		exit(-1);
	}
	/* Try to set, then cancel before it should go off */
	ret = snprintf(buf, sizeof(buf), "%llx", read_tsc() + sec2tsc(1));
	ret = write(timerfd, buf, ret);
	if (ret <= 0) {
		perror("Failed to set timer");
		exit(-1);
	}
	ret = snprintf(buf, sizeof(buf), "cancel");
	ret = write(ctlfd, buf, ret);
	if (ret <= 0) {
		perror("Failed to cancel timer");
		exit(-1);
	}
	uthread_sleep(2);
	printf("No alarm should have fired yet\n");
	/* Try to set and receive */
	ret = snprintf(buf, sizeof(buf), "%llx", read_tsc() + sec2tsc(1));
	ret = write(timerfd, buf, ret);
	if (ret <= 0) {
		perror("Failed to set timer");
		exit(-1);
	}
	uthread_sleep(2);
	close(ctlfd);
	/* get crazy: post the timerfd to #s, then sleep (or even try to exit), and
	 * then echo into it remotely!  A few limitations:
	 * - if the process is DYING, you won't be able to send an event to it.
	 * - the process won't leave DYING til the srv file is removed. */
	srvfd = open("#s/alarmtest", O_WRONLY | O_CREAT | O_EXCL, 0666);
	if (srvfd < 0) {
		perror("Failed to open srv file");
		exit(-1);
	}
	ret = snprintf(buf, sizeof(buf), "%d", timerfd);
	ret = write(srvfd, buf, ret);
	if (ret <= 0) {
		perror("Failed to post timerfd");
		exit(-1);
	}
	printf("Sleeping for 10 sec, try to echo 111 > '#s/alarmtest' now!\n");
	uthread_sleep(10);
	ret = unlink("#s/alarmtest");
	if (ret < 0) {
		perror("Failed to remove timerfd from #s, proc will never be freed");
		exit(-1);
	}
	printf("Done\n");
	return 0;
}