Example #1
0
int main(int argc, char** argv)
{
	/* this program should only be started from the kernel for tests */
	printf("[user] Attempting to read ucq messages from test_ucq().  "
	       "Don't call this manually.\n");
	/* Map into a known, extremely ghetto location.  The kernel knows to look
	 * here. */
	struct ucq *ucq = mmap((void*)USTACKTOP, PGSIZE, PROT_WRITE | PROT_READ,
	                       MAP_POPULATE, -1, 0);
	assert((uintptr_t)ucq == USTACKTOP);
	/* Now init it */
	uintptr_t two_pages = (uintptr_t)mmap(0, PGSIZE * 2, PROT_WRITE | PROT_READ,
	                                      MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
	assert(two_pages);
	ucq_init_raw(ucq, two_pages, two_pages + PGSIZE);
	printf("[user] UCQ %08p initialized\n", ucq);
	/* try to get a simple message */
	struct event_msg msg;
	/* 1: Spin til we can get a message (0 on success breaks) */
	while (get_ucq_msg(ucq, &msg))
		cpu_relax();
	printf("[user] Got simple message type %d(7) with A2 %08p(0xdeadbeef)\n",
	       msg.ev_type, msg.ev_arg2);
	/* 2: get a bunch */
	for (int i = 0; i < 5000; i++) {
		while (get_ucq_msg(ucq, &msg))
			cpu_relax();
		assert(msg.ev_type == i);
	}
	printf("[user] #2 Received a bunch!  Last one was %d(4999), "
	       "extra pages %d(6, if #3 is 1000 and was blasted already)\n",
	       msg.ev_type, atomic_read(&ucq->nr_extra_pgs));
	/* 3: test chaining */
	while (atomic_read(&ucq->nr_extra_pgs) < 2)
		cpu_relax();
	printf("[user] #3 There's now a couple pages (%d), trying to receive...\n",
	       atomic_read(&ucq->nr_extra_pgs));
	/* this assumes 1000 is enough for a couple pages */
	for (int i = 0; i < 1000; i++) {
		while (get_ucq_msg(ucq, &msg))
			cpu_relax();
		assert(msg.ev_type == i);
	}
	printf("[user] Done, extra pages: %d(0)\n", atomic_read(&ucq->nr_extra_pgs));
	int extra = 0;
	while (!get_ucq_msg(ucq, &msg)) {
		printf("[user] got %d extra messages in the ucq, type %d\n", ++extra,
		       msg.ev_type);
	}
	printf("[user] Spinning...\n");
	while(1);

	return 0;
}
Example #2
0
/* Attempts to handle a message.  Returns 1 if we dequeued a msg, 0 o/w. */
int handle_one_mbox_msg(struct event_mbox *ev_mbox)
{
	struct event_msg local_msg;
	unsigned int ev_type;
	/* get_ucq returns 0 on success, -1 on empty */
	if (get_ucq_msg(&ev_mbox->ev_msgs, &local_msg) == -1)
		return 0;
	ev_type = local_msg.ev_type;
	assert(ev_type < MAX_NR_EVENT);
	printd("[event] UCQ (mbox %08p), ev_type: %d\n", ev_mbox, ev_type);
	if (ev_handlers[ev_type])
		ev_handlers[ev_type](&local_msg, ev_type);
	return 1;
}
Example #3
0
/* Somewhat ghetto helper, for the lazy.  If all you care about is an event
 * number, this will see if the event happened or not.  It will try for a
 * message, but if there is none, it will go for a bit.  Note that multiple
 * bit messages will turn into just one bit. */
unsigned int get_event_type(struct event_mbox *ev_mbox)
{
	struct event_msg local_msg = {0};
	/* UCQ returns 0 on success, so this will dequeue and return the type. */
	if (!get_ucq_msg(&ev_mbox->ev_msgs, &local_msg)) {
		return local_msg.ev_type;
	}
	if (BITMASK_IS_CLEAR(&ev_mbox->ev_bitmap, MAX_NR_EVENT))
		return EV_NONE;	/* aka, 0 */
	for (int i = 0; i < MAX_NR_EVENT; i++) {
		if (GET_BITMASK_BIT(ev_mbox->ev_bitmap, i)) {
			CLR_BITMASK_BIT_ATOMIC(ev_mbox->ev_bitmap, i);
			return i;
		}
	}
	return EV_NONE;
}