Commit ba541361 authored by Michael Quigley's avatar Michael Quigley
Browse files

Added poll_recv fuctions to conform to new libfipc functions. Added tests for new thc_async_recv.

parent 3b01129d
Subproject commit 4d3e568dcf78e3a9acd863837e383df804d44eb1
Subproject commit 6bbedfeab26e1faa4584d78663cba021cd9faf18
......@@ -1022,7 +1022,7 @@ static void thc_yieldto_with_cont(void *a, void *arg) {
thc_awe_execute_0(awe);
}
void THCYieldToId(uint32_t id_to, uint32_t id_from) {
void THCYieldToIdAndSave(uint32_t id_to, uint32_t id_from) {
awe_t *awe_ptr = (awe_t *)awe_mapper_get_awe_ptr(id_to);
if (PTS() == awe_ptr->pts) {
CALL_CONT_LAZY_AND_SAVE((void*)&thc_yieldto_with_cont, id_from, (void*)awe_ptr);
......@@ -1035,8 +1035,21 @@ void THCYieldToId(uint32_t id_to, uint32_t id_from) {
THCSchedule(awe_ptr);
}
}
EXPORT_SYMBOL(THCYieldToIdAndSave);
void THCYieldToId(uint32_t id_to)
{
awe_t *awe_ptr = (awe_t *)awe_mapper_get_awe_ptr(id_to);
if (PTS() == awe_ptr->pts) {
CALL_CONT_LAZY((void*)&thc_yieldto_with_cont, (void*)awe_ptr);
}
else {
THCSchedule(awe_ptr);
}
}
EXPORT_SYMBOL(THCYieldToId);
void THCYieldTo(awe_t *awe_ptr) {
if (PTS() == awe_ptr->pts) {
CALL_CONT_LAZY((void*)&thc_yieldto_with_cont, (void*)awe_ptr);
......
#include <thc_ipc.h>
#include <thc_ipc_types.h>
#include <libfipc_types.h>
#include <awe-mapper.h>
//assumes msg is a valid received message
static int recv_predicate(struct fipc_message* msg, void* data)
static int thc_recv_predicate(struct fipc_message* msg, void* data)
{
struct predicate_payload* payload_ptr = (struct predicate_payload*)data;
......@@ -19,12 +20,31 @@ static int recv_predicate(struct fipc_message* msg, void* data)
}
else
{
payload_ptr->actual_msg_id = THC_MSG_ID(msg);
return 0; //message not for this awe
}
}
//assumes msg is a valid received message
static int poll_recv_predicate(struct fipc_message* msg, void* data)
{
struct predicate_payload* payload_ptr = (struct predicate_payload*)data;
if( THC_MSG_TYPE(msg) == (uint32_t)msg_type_request )
{
payload_ptr->msg_type = msg_type_request;
return 1;
}
else
{
payload_ptr->actual_msg_id = THC_MSG_ID(msg);
return 0; //message not for this awe
}
}
int thc_ipc_recv(struct fipc_ring_channel *chnl, unsigned long msg_id, struct fipc_message** out_msg)
int thc_ipc_recv(struct fipc_ring_channel *chnl,
unsigned long msg_id,
struct fipc_message** out_msg)
{
struct predicate_payload payload = {
.expected_msg_id = msg_id
......@@ -32,7 +52,7 @@ int thc_ipc_recv(struct fipc_ring_channel *chnl, unsigned long msg_id, struct fi
int ret;
while( true )
{
ret = fipc_recv_msg_if(chnl, recv_predicate, &payload, out_msg);
ret = fipc_recv_msg_if(chnl, thc_recv_predicate, &payload, out_msg);
if( !ret ) //message for us
{
if( payload.msg_type == msg_type_response )
......@@ -43,10 +63,12 @@ int thc_ipc_recv(struct fipc_ring_channel *chnl, unsigned long msg_id, struct fi
}
else if( ret == -ENOMSG ) //message not for us
{
THCYieldToId((uint32_t)THC_MSG_ID(*out_msg), (uint32_t) msg_id);
printk(KERN_ERR "yielding to\n");
THCYieldToIdAndSave((uint32_t)payload.actual_msg_id, (uint32_t) msg_id);
}
else if( ret == -EWOULDBLOCK ) //no message, Yield
{
printk(KERN_ERR "yielding\n");
THCYieldAndSave((uint32_t) msg_id);
}
else
......@@ -56,3 +78,81 @@ int thc_ipc_recv(struct fipc_ring_channel *chnl, unsigned long msg_id, struct fi
}
}
}
EXPORT_SYMBOL(thc_ipc_recv);
int thc_poll_recv_group(struct thc_channel_group* chan_group,
struct thc_channel_group_item** chan_group_item,
struct fipc_message** out_msg)
{
struct thc_channel_group_item* curr_item;
struct fipc_message* recv_msg;
int ret;
list_for_each_entry(curr_item, &(chan_group->head), list)
{
ret = thc_poll_recv(curr_item, &recv_msg);
if( !ret )
{
*chan_group_item = curr_item;
*out_msg = recv_msg;
return 0;
}
}
return -EWOULDBLOCK;
}
EXPORT_SYMBOL(thc_poll_recv_group);
int thc_poll_recv(struct thc_channel_group_item* item,
struct fipc_message** out_msg)
{
struct predicate_payload payload;
int ret;
while( true )
{
ret = fipc_recv_msg_if(item->channel, poll_recv_predicate, &payload, out_msg);
if( !ret ) //message for us
{
return 0;
}
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
{
return ret;
}
else
{
printk(KERN_ERR "error in thc_poll_recv: %d\n", ret);
return ret;
}
}
}
EXPORT_SYMBOL(thc_poll_recv);
int thc_channel_group_init(struct thc_channel_group* channel_group)
{
INIT_LIST_HEAD(&(channel_group->head));
channel_group->size = 0;
return 0;
}
EXPORT_SYMBOL(thc_channel_group_init);
int thc_channel_group_add(struct thc_channel_group* channel_group,
struct thc_channel_group_item* item)
{
list_add_tail(&(item->list), &(channel_group->head));
channel_group->size++;
return 0;
}
EXPORT_SYMBOL(thc_channel_group_add);
......@@ -275,7 +275,10 @@ void THCYieldTo(awe_t *awe_ptr);
//id_to is the id that corresponds to the awe that should be yielded to.
//id_from is the id that corresponds to the awe that should save the
//current context.
void THCYieldToId(uint32_t id_to, uint32_t id_from);
void THCYieldToIdAndSave(uint32_t id_to, uint32_t id_from);
//Yields to without saving curent awe id.
void THCYieldToId(uint32_t id_to);
// Cancellation actions. These are executed in LIFO order when cancellation
// occurs. Once cancellation has been requested, it is assumed that no
......
......@@ -2,25 +2,24 @@
#define THC_IPC_H
#include <libfipc.h>
#include <thc_ipc_types.h>
#define THC_MSG_TYPE(msg) ((msg)->flags)
#define THC_MSG_TYPE(msg) ((msg)->regs[(FIPC_NR_REGS) - 2])
#define THC_MSG_ID(msg) ((msg)->regs[(FIPC_NR_REGS) - 1])
int thc_ipc_recv(struct fipc_ring_channel *chnl, unsigned long msg_id, struct fipc_message** out_msg);
typedef enum {
msg_type_unspecified,
msg_type_request,
msg_type_response,
} msg_type_t;
int thc_ipc_recv(struct fipc_ring_channel *chnl,
unsigned long msg_id,
struct fipc_message** out_msg);
static struct predicate_payload
{
unsigned long expected_msg_id;
msg_type_t msg_type;
};
int thc_poll_recv_group(struct thc_channel_group* chan_group,
struct thc_channel_group_item** chan_group_item,
struct fipc_message** out_msg);
int thc_poll_recv(struct thc_channel_group_item* item,
struct fipc_message** out_msg);
int thc_channel_group_init(struct thc_channel_group* channel_group);
int thc_channel_group_add(struct thc_channel_group* channel_group,
struct thc_channel_group_item* item);
#endif
/local/sda4/xcap-async-module/libasync/tests/libasync_test.ko
/local/sda4/xcap-async-module/libasync/tests/../src/common/awe-mapper.o /local/sda4/xcap-async-module/libasync/tests/../src/common/thc.o /local/sda4/xcap-async-module/libasync/tests/../src/common/thc_ipc.o /local/sda4/xcap-async-module/libasync/tests/../src/common/thcsync.o /local/sda4/xcap-async-module/libasync/tests/../../fast-ipc-module/src/common/ipc.o /local/sda4/xcap-async-module/libasync/tests/callee.o /local/sda4/xcap-async-module/libasync/tests/caller.o /local/sda4/xcap-async-module/libasync/tests/main.o
ASYNC_OBJS_DIR=../src/common
RPC_OBJS_DIR=../../fast-ipc-module/src/common
CFLAGS_ipc.o = -O2 -DPOLL -fno-ipa-cp -fno-ipa-sra
#CFLAGS_ring-channel.o = -I$(RPC_OBJS_DIR)../../IPC -I$(RING_CHAN_DIR) -fno-ipa-cp -fno-ipa-sra
EXTRA_CFLAGS=-DDEBUG_OUTPUT
obj-m := libasync_test.o
ccflags-y += -O0 -fno-ipa-cp -fno-ipa-sra -I$(LIB_TEST_ASYNC_DIR)/../src/include -I$(LIB_TEST_ASYNC_DIR)/../../fast-ipc-module/src/include -I$(LIB_TEST_ASYNC_DIR)/../../fast-ipc-module/src/platform/kernel/include -DUSE_ASYNC -DCONFIG_LAZY_THC
libasync_test-objs = $(ASYNC_OBJS_DIR)/awe-mapper.o $(ASYNC_OBJS_DIR)/thc.o $(ASYNC_OBJS_DIR)/thc_ipc.o $(ASYNC_OBJS_DIR)/thcsync.o $(RPC_OBJS_DIR)/ipc.o callee.o caller.o main.o
LIB_TEST_ASYNC_DIR=$(PWD)
KDIR = /lib/modules/`uname -r`/build
export LIB_TEST_ASYNC_DIR
module:
make -C $(KDIR) M=$(LIB_TEST_ASYNC_DIR) modules
clean:
sudo rm -rf *.o
sudo rm -rf *.ko
sudo rm -rf *.symvers
sudo rm -rf *.order
sudo rm -rf *.mod.c
/*
* 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 "../../fast-ipc-module/src/platform/kernel/tests/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;
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 "../../fast-ipc-module/src/platform/kernel/tests/test_helpers.h"
static inline int send_and_get_response(
struct fipc_ring_channel *chan,
struct fipc_message *request,
struct fipc_message **response,
uint32_t msg_id)
{
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
*/
ret = thc_ipc_recv(chan, msg_id, &resp);
if (ret) {
pr_err("failed to get a response, ret = %d\n", ret);
goto fail2;
}
*response = resp;
printk(KERN_ERR "got result\n");
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);
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 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
async_add_nums(struct fipc_ring_channel *chan, unsigned long trans,
unsigned long res1)
{
struct fipc_message *request;
struct fipc_message *response;
uint32_t msg_id;
int ret;
/*
* Set up request
*/
ret = test_fipc_blocking_send_start(chan, &request);
if (ret) {
pr_err("Error getting send message, ret = %d\n", ret);
goto fail;
}
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);
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;
}
int caller(void *_caller_channel_header)
{
struct fipc_ring_channel *chan = _caller_channel_header;
unsigned long transaction_id = 0;
unsigned long start, end;
int ret = 0;
volatile void ** frame = (volatile void**)__builtin_frame_address(0);
volatile void *ret_addr = *(frame + 1);
*(frame + 1) = NULL;
thc_init();
/*
* Add nums
*/
DO_FINISH({
while(transaction_id < TRANSACTIONS)
{
ASYNC({
transaction_id++;
ret = async_add_nums(chan, transaction_id, 1000);
if (ret) {
pr_err("error doing null invocation, ret = %d, exiting...\n",
ret);
}
});
}
});
pr_err("Complete\n");
thc_done();
*(frame + 1) = ret_addr;
return ret;
}