Commit d64a5f3f authored by Charlie Jacobsen's avatar Charlie Jacobsen
Browse files

Merge branch 'master' of gitlab.flux.utah.edu:xcap/xcap-async-module

parents 9f662cc8 a92837e8
......@@ -114,6 +114,8 @@ AC_CONFIG_FILES(
src/tests/simple/Kbuild
src/tests/dispatch/Kbuild
src/tests/ctx-switch/Kbuild
src/tests/async-msg-benchmarks/Kbuild
)
AC_OUTPUT
Subproject commit 255e1b8cbdba34386bacaac425792d91478675e2
Subproject commit 2cef3d068d3ed2da556d775f8571f5c2c6b67d63
......@@ -558,8 +558,13 @@ static void thc_end_rts(void) {
// book-keeping: once the dispatch loop is done, then the
// number of stacks on our free list should equal the number
// allocated from the OS.
void* next_stack;
while (pts->free_stacks != NULL) {
pts->free_stacks = pts->free_stacks->next;
next_stack = pts->free_stacks->next;
#ifdef LINUX_KERNEL
kfree(pts->free_stacks);
#endif
pts->free_stacks = next_stack;
#ifndef NDEBUG
pts->stackMemoriesDeallocated ++;
#endif
......
......@@ -79,7 +79,6 @@ thc_ipc_recv(struct fipc_ring_channel *chnl,
}
else if( ret == -ENOMSG ) //message not for us
{
printk(KERN_ERR "yielding to\n");
THCYieldToIdAndSave((uint32_t)payload.actual_msg_id, (uint32_t) msg_id);
}
else if( ret == -EWOULDBLOCK ) //no message, Yield
......@@ -139,7 +138,6 @@ thc_poll_recv(struct thc_channel_group_item* item,
}
else if( ret == -ENOMSG ) //message not for us
{
printk(KERN_ERR "yielding to\n");
THCYieldToId((uint32_t)payload.actual_msg_id);
}
else if( ret == -EWOULDBLOCK ) //no message, return
......
......@@ -16,7 +16,7 @@
#ifdef LINUX_KERNEL
#define AWE_TABLE_COUNT 128
#define AWE_TABLE_COUNT 1024
struct awe_table
{
......
obj-m += simple/
obj-m += dispatch/
obj-m += ctx-switch/
obj-m += async-msg-benchmarks/
......@@ -3,3 +3,5 @@
install-tests:
cp $(LIBASYNC_TESTS_KBUILD)/simple/libasync_test_simple.ko $(D)
cp $(LIBASYNC_TESTS_KBUILD)/dispatch/libfipc_test_dispatch_loop.ko $(D)
cp $(LIBASYNC_TESTS_KBUILD)/ctx-switch/ctx_switch_test.ko $(D)
cp $(LIBASYNC_TESTS_KBUILD)/async-msg-benchmarks/libasync_test_msgs.ko $(D)
# @ASYNC_AUTOCONF_NOTICE@
# Magic line so we can do out-of-source build
src = @abs_top_srcdir@/src/tests/async-msg-benchmarks
obj-m = libasync_test_msgs.o
# Paths are relative to simple/ build dir
libasync_test_msgs-y += ../test_helpers.o main.o callee.o caller.o
# LIBASYNC_PATH and LIBFIPC_LIB are defined (and exported) in
# src/Makefile.am.
libasync_test_msgs-y += ../../$(LIBASYNC_PATH)
libasync_test_msgs-y += ../../$(LIBFIPC_LIB)
# Add -DCHECK_MESSAGES to check that message values contain what is expected
ccflags-y += $(CFLAGS) $(AM_CPPFLAGS) $(AM_CFLAGS)
/*
* callee.c
*
* Code for the "callee side" of the channel
*
* Copyright: University of Utah
*/
#include <linux/kernel.h>
#include <libfipc.h>
#include "rpc.h"
#include "../test_helpers.h"
#include <thc_ipc.h>
/*
* We use "noinline" because we want the function call to actually
* happen.
*/
static unsigned long noinline
null_invocation(void)
{
return 9;
}
static unsigned long noinline
add_constant(unsigned long trans)
{
return trans + 50;
}
static unsigned long noinline
add_nums(unsigned long trans, unsigned long res1)
{
return trans+res1;
}
static unsigned long noinline
add_3_nums(unsigned long trans, unsigned long res1, unsigned long res2)
{
return add_nums(trans, res1) + res2;
}
static unsigned long noinline
add_4_nums(unsigned long trans, unsigned long res1, unsigned long res2,
unsigned long res3)
{
return add_nums(trans, res1) + add_nums(res2, res3);
}
static unsigned long noinline
add_5_nums(unsigned long trans, unsigned long res1, unsigned long res2,
unsigned long res3, unsigned long res4)
{
return add_4_nums(trans,res1,res2,res3) + res4;
}
static unsigned long noinline
add_6_nums(unsigned long trans, unsigned long res1, unsigned long res2,
unsigned long res3, unsigned long res4, unsigned long res5)
{
return add_3_nums(trans,res1,res2) + add_3_nums(res3,res4,res5);
}
static inline int send_response(struct fipc_ring_channel *chnl,
struct fipc_message *recvd_msg,
unsigned long val, enum fn_type type)
{
int ret;
struct fipc_message *response;
/*
* Mark recvd msg slot as available
*/
ret = fipc_recv_msg_end(chnl, recvd_msg);
if (ret) {
pr_err("Error marking msg as recvd");
return ret;
}
/*
* Response
*/
ret = test_fipc_blocking_send_start(chnl, &response);
if (ret) {
pr_err("Error getting send slot");
return ret;
}
THC_MSG_TYPE(response) = msg_type_response;
THC_MSG_ID(response) = THC_MSG_ID(recvd_msg);
set_fn_type(response, type);
response->regs[0] = val;
ret = fipc_send_msg_end(chnl, response);
if (ret) {
pr_err("Error marking message as sent");
return ret;
}
return 0;
}
int callee(void *_callee_channel_header)
{
int ret = 0;
unsigned long temp_res;
struct fipc_ring_channel *chan = _callee_channel_header;
struct fipc_message *recvd_msg;
unsigned long transaction_id = 0;
enum fn_type type;
for (transaction_id = 0;
transaction_id < TRANSACTIONS*2;
transaction_id++) {
/*
* Try to receive a message
*/
ret = test_fipc_blocking_recv_start(chan, &recvd_msg);
if (ret) {
pr_err("Error receiving message, ret = %d, exiting...", ret);
goto out;
}
/*
* Dispatch on message type
*/
type = get_fn_type(recvd_msg);
switch(type) {
case NULL_INVOCATION:
temp_res = null_invocation();
break;
case ADD_CONSTANT:
temp_res = add_constant(fipc_get_reg0(recvd_msg));
break;
case ADD_NUMS:
temp_res = add_nums(fipc_get_reg0(recvd_msg),
fipc_get_reg1(recvd_msg));
break;
case ADD_3_NUMS:
temp_res = add_3_nums(fipc_get_reg0(recvd_msg),
fipc_get_reg1(recvd_msg),
fipc_get_reg2(recvd_msg));
break;
case ADD_4_NUMS:
temp_res = add_4_nums(fipc_get_reg0(recvd_msg),
fipc_get_reg1(recvd_msg),
fipc_get_reg2(recvd_msg),
fipc_get_reg3(recvd_msg));
break;
case ADD_5_NUMS:
temp_res = add_5_nums(fipc_get_reg0(recvd_msg),
fipc_get_reg1(recvd_msg),
fipc_get_reg2(recvd_msg),
fipc_get_reg3(recvd_msg),
fipc_get_reg4(recvd_msg));
break;
case ADD_6_NUMS:
temp_res = add_6_nums(fipc_get_reg0(recvd_msg),
fipc_get_reg1(recvd_msg),
fipc_get_reg2(recvd_msg),
fipc_get_reg3(recvd_msg),
fipc_get_reg4(recvd_msg),
fipc_get_reg5(recvd_msg));
break;
default:
pr_err("Bad function type %d, exiting...\n", type);
ret = -EINVAL;
goto out;
}
/*
* Send response back
*/
ret = send_response(chan, recvd_msg, temp_res, type);
if (ret) {
pr_err("Error sending response back, ret = %d, exiting...", ret);
goto out;
}
}
out:
return ret;
}
/*
* caller.c
*
* The "caller side" of the channel
*
* Copyright: University of Utah
*/
#include <linux/random.h>
#include "rpc.h"
#include <thc_ipc.h>
#include <thc.h>
#include <thcinternal.h>
#include <awe_mapper.h>
#include "../test_helpers.h"
static unsigned long msg_times[TRANSACTIONS];
static inline int send_and_get_response(
struct fipc_ring_channel *chan,
struct fipc_message *request,
struct fipc_message **response,
uint32_t msg_id,
bool is_async)
{
int ret;
struct fipc_message *resp;
/*
* Mark the request as sent
*/
ret = fipc_send_msg_end(chan, request);
if (ret) {
pr_err("failed to mark request as sent, ret = %d\n", ret);
goto fail1;
}
/*
* Try to get the response
*/
if( is_async )
{
ret = thc_ipc_recv(chan, msg_id, &resp);
}
else
{
ret = test_fipc_blocking_recv_start(chan, &resp);
}
if (ret) {
pr_err("failed to get a response, ret = %d\n", ret);
goto fail2;
}
*response = resp;
ret = fipc_recv_msg_end(chan, resp);
if (ret) {
pr_err("Error finishing receipt of response, ret = %d\n", ret);
return ret;
}
return 0;
fail2:
fail1:
return ret;
}
static inline int finish_response_check_fn_type(struct fipc_ring_channel *chnl,
struct fipc_message *response,
enum fn_type expected_type)
{
int ret;
enum fn_type actual_type = get_fn_type(response);
ret = fipc_recv_msg_end(chnl, response);
if (ret) {
pr_err("Error finishing receipt of response, ret = %d\n", ret);
return ret;
} else if (actual_type != expected_type) {
pr_err("Unexpected fn type: actual = %d, expected = %d\n",
actual_type, expected_type);
return -EINVAL;
} else {
return 0;
}
}
static inline int finish_response_check_fn_type_and_reg0(
struct fipc_ring_channel *chnl,
struct fipc_message *response,
enum fn_type expected_type,
unsigned long expected_reg0)
{
int ret;
enum fn_type actual_type = get_fn_type(response);
unsigned long actual_reg0 = fipc_get_reg0(response);
if (actual_type != expected_type) {
pr_err("Unexpected fn type: actual = %d, expected = %d\n",
actual_type, expected_type);
return -EINVAL;
} else if (actual_reg0 != expected_reg0) {
pr_err("Unexpected return value (reg0): actual = 0x%lx, expected = 0x%lx\n",
actual_reg0, expected_reg0);
return -EINVAL;
} else {
return 0;
}
}
static int noinline __used add_nums(struct fipc_ring_channel *chan,
unsigned long trans,
unsigned long res1,
bool is_async)
{
struct fipc_message *request;
struct fipc_message *response;
unsigned long start_time, stop_time;
uint32_t msg_id;
int ret;
/*
* Set up request
*/
start_time = test_fipc_start_stopwatch();
ret = test_fipc_blocking_send_start(chan, &request);
if (ret) {
pr_err("Error getting send message, ret = %d\n", ret);
goto fail;
}
if( is_async )
{
msg_id = awe_mapper_create_id();
}
THC_MSG_TYPE(request) = msg_type_request;
THC_MSG_ID(request) = msg_id;
set_fn_type(request, ADD_NUMS);
fipc_set_reg0(request, trans);
fipc_set_reg1(request, res1);
/*
* Send request, and get response
*/
ret = send_and_get_response(chan, request, &response, msg_id, is_async);
stop_time = test_fipc_stop_stopwatch();
msg_times[trans] = stop_time - start_time;
if (ret) {
pr_err("Error getting response, ret = %d\n", ret);
goto fail;
}
/*
* Maybe check message
*/
return finish_response_check_fn_type_and_reg0(
chan,
response,
ADD_NUMS,
trans + res1);
fail:
return ret;
}
static int msg_test(void* _caller_channel_header, bool is_async)
{
struct fipc_ring_channel *chan = _caller_channel_header;
unsigned long transaction_id = 0;
unsigned long start_time, stop_time;
int ret = 0;
thc_init();
preempt_disable();
local_irq_disable();
transaction_id = 0;
/*
* Add nums
*/
LCD_MAIN({
DO_FINISH({
start_time = test_fipc_start_stopwatch();
while(transaction_id < TRANSACTIONS)
{
if( is_async )
{
ASYNC({
ret = add_nums(chan, transaction_id, 1000, is_async);
if (ret) {
pr_err("error doing null invocation, ret = %d\n",
ret);
}
});
}
else
{
ret = add_nums(chan, transaction_id, 1000, is_async);
if (ret) {
pr_err("error doing null invocation, ret = %d\n",
ret);
}
}
transaction_id++;
}
stop_time = test_fipc_stop_stopwatch();
});
});
preempt_enable();
local_irq_enable();
thc_done();
pr_err("Complete\n");
printk(KERN_ERR "Avg throughput in msgs/10000 cycles: %lu\n", (TRANSACTIONS*10000) / (stop_time - start_time));
printk(KERN_ERR "Timing results of performing %d message transactions:\n", TRANSACTIONS);
test_fipc_dump_time(msg_times, TRANSACTIONS);
return ret;
}
int caller(void *_caller_channel_header)
{
int ret = 0;
printk(KERN_ERR "Testing asynchronous:\n");
ret = msg_test(_caller_channel_header, true);
if( ret )
{
printk(KERN_ERR "Error with asynchronous message test.");
return ret;
}
printk(KERN_ERR "Testing synchronous:\n");
ret = msg_test(_caller_channel_header, false);
if( ret )
{
printk(KERN_ERR "Error with synchronous message test.");
return ret;
}
return ret;
}
/*
* main.c
*
* Contains init/exit for rpc test
*/
#include <libfipc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include "../test_helpers.h"
#include "rpc.h"
#define CALLER_CPU 1
#define CALLEE_CPU 3
#define CHANNEL_ORDER 2 /* channel is 2^CHANNEL_ORDER pages */
MODULE_LICENSE("GPL");
static int setup_and_run_test(void)
{
int ret;
struct fipc_ring_channel *caller_header, *callee_header;
struct task_struct *caller_thread, *callee_thread;
/*
* Initialize fipc
*/
ret = fipc_init();
if (ret) {
pr_err("Error init'ing libfipc, ret = %d\n", ret);
goto fail0;
}
/*
* Set up channel
*/
ret = test_fipc_create_channel(CHANNEL_ORDER, &caller_header,
&callee_header);
if (ret) {
pr_err("Error creating channel, ret = %d\n", ret);
goto fail1;
}
/*
* Set up threads
*/
caller_thread = test_fipc_spawn_thread_with_channel(caller_header,
caller,
CALLER_CPU);
if (!caller_thread) {
pr_err("Error setting up caller thread\n");
goto fail2;
}
callee_thread = test_fipc_spawn_thread_with_channel(callee_header,
callee,
CALLEE_CPU);
if (!callee_thread) {
pr_err("Error setting up callee thread\n");
goto fail3;
}
/*
* Wake them up; they will run until they exit.
*/
wake_up_process(caller_thread);
wake_up_process(callee_thread);
msleep(1000);
/*
* Wait for them to complete, so we can tear things down
*/
ret = test_fipc_wait_for_thread(caller_thread);
if (ret)
pr_err("Caller returned non-zero exit status %d\n", ret);
ret = test_fipc_wait_for_thread(callee_thread);
if (ret)
pr_err("Callee returned non-zero exit status %d\n", ret);
/*
* Tear things down
*/
test_fipc_free_channel(CHANNEL_ORDER, caller_header, callee_header);
fipc_fini();
return 0;
fail3:
test_fipc_release_thread(caller_thread);
fail2:
test_fipc_free_channel(CHANNEL_ORDER, caller_header, callee_header);
fail1:
fipc_fini();
fail0:
return ret;
}
static int __init rpc_init(void)