Commit 724861a8 authored by Scotty Bauer's avatar Scotty Bauer
Browse files

Added new function to IPC API: attach_thread_to_channel.



Split create_channel into two functions:
create_channel simply allocates space for the channel and
the ring buffer.

attach_thread_to_channel:
This function creates a kthread and pins it to a specific core.
It takes a funciton pointer to the function you want to execute.

**NOTE**
The timing code is still using the API, It will be fixed in future
commits

Signed-off-by: Scotty Bauer's avatarScott Bauer <sbauer@eng.utah.edu>
parent ec05a54d
......@@ -27,9 +27,6 @@ static unsigned int send_message = 0xBADBEEF;
static unsigned int rx_msg_avail = 0xBADBEEF;
static unsigned int trans_complete = 0xC1346BAD;
extern int dispatch(void *data);
static inline void monitor_mwait(unsigned long rcx, volatile uint32_t *rax,
unsigned long wait_type)
{
......@@ -86,16 +83,47 @@ static int wait_for_rx_slot(struct ipc_message *imsg)
}
struct task_struct *attach_thread_to_channel(struct ttd_ring_channel *chan,
int CPU_PIN,
int (*threadfn)(void *data)) {
struct cpumask cpu_core;
if (!chan)
return NULL;
if (CPU_PIN > num_online_cpus()) {
pr_err("Trying to pin on cpu > than avail # cpus\n");
return NULL;
}
chan->thread = kthread_create(threadfn, (void *)chan,
"AsyncIPC.%u", CPU_PIN);
if (IS_ERR(chan->thread)) {
pr_err("Error while creating kernel thread\n");
return NULL;
}
get_task_struct(chan->thread);
cpumask_clear(&cpu_core);
cpumask_set_cpu(CPU_PIN ,&cpu_core);
set_cpus_allowed_ptr(chan->thread, &cpu_core);
return chan->thread;
}
/*
Create a channel with a ring-buffer of size pages
Create a communication thread on CPU
*/
* Create a channel with a ring-buffer of size pages
*/
struct ttd_ring_channel *create_channel(unsigned long size_pages, unsigned CPU)
struct ttd_ring_channel *create_channel(unsigned long size_pages)
{
int i,ret;
struct cpumask cpu_core;
struct ttd_ring_channel *channel;
......@@ -130,25 +158,6 @@ struct ttd_ring_channel *create_channel(unsigned long size_pages, unsigned CPU)
for (i = 0; i < (size_pages * PAGE_SIZE)/sizeof(int); i++)
*((int *)channel->tx.recs+i) = tx_slot_avail;
channel->thread = kthread_create(&dispatch, (void *)channel,
"betaIPC.%u", CPU);
if (IS_ERR(channel->thread)) {
ttd_ring_channel_free(channel);
kfree(channel);
pr_err("Error while creating kernel thread\n");
return NULL;
}
get_task_struct(channel->thread);
cpumask_clear(&cpu_core);
cpumask_set_cpu(CPU,&cpu_core);
set_cpus_allowed_ptr(channel->thread, &cpu_core);
return channel;
}
EXPORT_SYMBOL(create_channel);
......
......@@ -28,7 +28,10 @@ struct ipc_message{
volatile uint32_t msg_status;
}__attribute__((packed));
struct ttd_ring_channel *create_channel(unsigned long size_pages, unsigned CPU);
struct ttd_ring_channel *create_channel(unsigned long size_pages);
struct task_struct *attach_thread_to_channel(struct ttd_ring_channel *chan,
int CPU_PIN,
int (*threadfn)(void *data));
void free_channel(struct ttd_ring_channel *channel);
void send(struct ttd_ring_channel *tx, struct ipc_message *trans);
struct ipc_message *recv(struct ttd_ring_channel *rx);
......
......@@ -162,7 +162,7 @@ static unsigned long add_6_nums(unsigned long trans, unsigned long res1,
return result;
}
void callee(struct ttd_ring_channel *chan)
int callee(void *chan)
{
unsigned long num_transactions = 0;
unsigned long res1, res2, res3, res4, res5, res6;
......@@ -193,4 +193,5 @@ void callee(struct ttd_ring_channel *chan)
num_transactions++;
}
pr_err("Complete\n");
return 1;
}
......@@ -44,11 +44,12 @@ static unsigned long add_6_nums(unsigned long trans, unsigned long res1,
return add_3_nums(trans,res1,res2) + add_3_nums(res3,res4,res5);
}
void caller(struct ttd_ring_channel *chan)
int caller(void *channel)
{
unsigned long num_transactions = 0;
unsigned long temp_res = 0;
struct ttd_ring_channel *chan = channel;
struct ipc_message *msg;
while (num_transactions < TRANSACTIONS) {
msg = recv(chan);
......@@ -116,4 +117,5 @@ void caller(struct ttd_ring_channel *chan)
}
num_transactions++;
}
return 1;
}
......@@ -9,5 +9,5 @@ typedef enum {NULL_INVOCATION, ADD_CONSTANT, ADD_NUMS, ADD_3_NUMS,
#define TRANSACTIONS 12000
void callee(struct ttd_ring_channel *chan);
void caller(struct ttd_ring_channel *chan);
int callee(void *chan);
int caller(void *chan);
#include "rpc.h"
#include <linux/spinlock.h>
static volatile int migrate;
static spinlock_t lock = __SPIN_LOCK_UNLOCKED();
int dispatch(void *data)
{
/*
* Normally one person doesn't create both threads
* This means they both wont call the same dispatch function
* but since I've created two threads we need to seperate them
* into calle and callers.
* that is what this code below is doing
*/
spin_lock(&lock);
if(migrate == 0) {
migrate = 1;
spin_unlock(&lock);
callee(data);
free_channel(data);
return 1;
}
spin_unlock(&lock);
caller(data);
free_channel(data);
return 1;
}
......@@ -20,6 +20,10 @@
#include "rpc.h"
#define CHAN1_CPU 1
#define CHAN2_CPU 3
#define CHAN_NUM_PAGES 4
static struct ttd_ring_channel *chan1;
static struct ttd_ring_channel *chan2;
......@@ -27,18 +31,31 @@ MODULE_LICENSE("GPL");
static void setup_tests(void)
{
chan1 = create_channel(4,0);
chan1 = create_channel(CHAN_NUM_PAGES);
if (!chan1) {
pr_err("Failed to create channel 1");
return;
}
chan2 = create_channel(4,3);
chan2 = create_channel(CHAN_NUM_PAGES);
if (!chan2) {
pr_err("Failed to create channel 2");
free_channel(chan1);
return;
}
connect_channels(chan1,chan2);
connect_channels(chan1, chan2);
/* Create a thread for each channel to utilize, pin it to a core.
* Pass a function pointer to call on wakeup.
*/
if (attach_thread_to_channel(chan1, CHAN1_CPU, callee) == NULL ||
attach_thread_to_channel(chan2, CHAN2_CPU, caller) == NULL ) {
ttd_ring_channel_free(chan1);
ttd_ring_channel_free(chan2);
kfree(chan1);
kfree(chan2);
return;
}
ipc_start_thread(chan1);
ipc_start_thread(chan2);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment