Commit b4e2afa7 authored by Scotty Bauer's avatar Scotty Bauer

fixes/some timing one way

TODO directional and rtdsc() for RT latency and throughput
Signed-off-by: Scotty Bauer's avatarScott Bauer <sbauer@eng.utah.edu>
parent 46bee069
obj-m := betaModule2.o
CFLAGS_betaModule2.o = -DDEBUG -O2 -Wall
obj-m := test.o
#CFLAGS_test.o = -DDEBUG -DDEBUG_MWAIT_RETRY -DDEBUG_BOUNDS_CHECK -g -Wall
#CFLAGS_betaModule2.o = -DDEBUG -DDEBUG_MWAIT_RETRY -DDEBUG_BOUNDS_CHECK -g -Wall
#CFLAGS_ring-channel.o = -DDEBUG -DDEBUG_MWAIT_RETRY -DDEBUG_BOUNDS_CHECK -g -Wall
CFLAGS_test.o = -O2
CFLAGS_betaModule2.o = -O2
CFLAGS_ring-channel.o = -O2
test-objs := ./ring-chan/ring-channel.o ./betaModule2.o
KDIR := /lib/modules/`uname -r`/build
......
......@@ -12,8 +12,9 @@
#include <asm/mwait.h>
#include <asm/page_types.h>
#include <asm/cpufeature.h>
#include <linux/ktime.h>
#include "../ring-chan/ring-channel.h"
#include "ring-chan/ring-channel.h"
#include "../betaModule.h"
MODULE_LICENSE("GPL");
......@@ -25,6 +26,8 @@ static int CPU_NUM;
static char *msg = "12345678123456781234567812345678123456781234567812345678" \
"1234567";
static unsigned long start;
static unsigned long end;
/* Stolen and slightly modified from http://rosettacode.org/wiki/Rot-13 */
......@@ -51,15 +54,16 @@ static char *rot13(char *s, int amount)
static void assert_expect_and_zero(struct ipc_message *i_msg, int need_rot)
{
if (need_rot)
rot13(i_msg->message, 123);
rot13(i_msg->message, 60);
if (strncmp(i_msg->message, msg, 123) != 0)
if (strncmp(i_msg->message, msg, BUF_SIZE) != 0)
pr_debug("STRINGS DIFFERED IN CPU %d\n", CPU_NUM);
i_msg->monitor = 0;
// memset(i_msg->message, 0, 60);
i_msg->monitor = 0xC1346BAD;
}
static inline void monitor_mwait(unsigned long rcx, void *rax,
static inline void monitor_mwait(unsigned long rcx, volatile uint32_t *rax,
unsigned long wait_type)
{
......@@ -80,28 +84,40 @@ static inline void monitor_mwait(unsigned long rcx, void *rax,
mb();
}
local_irq_save(flags);
// local_irq_save(flags);
__monitor((void *)rax, 0, 0);
/* TODO comment for memory barrier, why is this necessary? */
mb();
__mwait(wait_type, rcx);
local_irq_restore(flags);
//local_irq_restore(flags);
}
static inline int trample_imminent(unsigned int *loc)
static inline int trample_imminent(struct ipc_message *loc)
{
return *loc == 0xbadc0de;
return (loc->monitor != 0xbadbeef);
}
static inline int trample_imminent_store(struct ttd_ring_channel *prod,
unsigned int prod_loc, unsigned int **t_loc)
unsigned int prod_loc, struct ipc_message **t_loc)
{
struct ipc_message *imsg;
imsg = (struct ipc_message *) ttd_ring_channel_get_rec_slow(prod, prod_loc);
*t_loc = imsg;
return (imsg->monitor != 0xbadbeef);
}
*t_loc = (unsigned int*) ttd_ring_channel_get_rec_slow(prod, prod_loc);
return ((*(*t_loc)) == 0xbadc0de);
static void write_protected_slot(struct ttd_ring_channel *cons,
unsigned long location)
{
unsigned long *write_loc;
write_loc = (unsigned long*) ttd_ring_channel_get_rec_slow(cons, location);
*write_loc = 0;
}
static int ipc_thread_func(void *input)
{
/* This will be a while true loop with timing code and mwaits
......@@ -112,6 +128,8 @@ static int ipc_thread_func(void *input)
byte boundary until it gets out of its OPT loop
*/
pr_debug("Hello from betaModule2\n");
struct file *filep = input;
struct ipc_container *container = NULL;
unsigned long ecx = 1; /*break of interrupt flag */
......@@ -121,6 +139,7 @@ static int ipc_thread_func(void *input)
unsigned int local_cons;
unsigned int *trample_loc;
struct ipc_message *imsg;
ktime_t start, end;
#if defined(DEBUG_MWAIT_RETRY)
unsigned long retry_count = 0;
......@@ -140,45 +159,58 @@ static int ipc_thread_func(void *input)
cons_channel = container->channel_rx;
/* PRODUCER */
write_protected_slot(cons_channel, 0);
local_cons = 0;
local_cons = 1;
/* 10 mil */
while(count < 10000000) {
start = ktime_get();
while(count < 5000000) {
/* POSSIBLE CACHE THRASHING WILE WAITING ??*/
/* TODO LETS DO BOTH METHODS, LETS MWAIT ON THE NIL */
/* AND LETS MWAIT ONT THE CONSUMER */
if(trample_imminent_store(cons_channel, local_prod, &trample_loc)) {
if(trample_imminent_store(cons_channel, local_cons, &imsg)) {
do{
monitor_mwait(ecx, trample_loc, cstate_wait);
pr_debug("Waiting in CPU%d on %p\n",
CPU_NUM, &imsg->monitor);
monitor_mwait(ecx, &imsg->monitor, cstate_wait);
#if defined(DEBUG_MWAIT_RETRY)
if(retry_count > 50) {
pr_debug("RETRY COUNT FAILED! MORE THAN "\
"50 WAITS on CPU %d\n", CPU_NUM);
pr_err("RETRY COUNT FAILED! MORE THAN "\
"50 WAITS on CPU %d with count %d\n",
CPU_NUM, count);
return -1;
}
retry_count++;
#endif
}while(trample_imminent(trample_loc));
}while(trample_imminent(imsg));
}
/* trample Location is now free for us to write */
imsg = (struct ipc_message *)trample_loc;
memcpy(imsg->message, msg, 63);
imsg->monitor = 0;
#if defined(DEBUG_BOUNDS_CHECK)
/* trample Location is now free for us to write */
if((unsigned long)imsg > end || (unsigned long)imsg < start) {
pr_err("OUT OF BOUNDS! with %p on CPU %d\n", imsg,
CPU_NUM);
break;
}
#endif
pr_debug("assert_expecting on count %d at loc %p\n",
count, imsg->message);
assert_expect_and_zero(imsg, 0);
pr_debug("Wrote to voltile var in cpu %d at loc %p\n",
CPU_NUM, &imsg->monitor);
ttd_ring_channel_inc_prod(prod_channel);
//ttd_ring_channel_inc_cons(cons_channel);
#if defined(DEBUG_MWAIT_RETRY)
retry_count = 0;
#endif
local_prod++;
local_cons++;
count++;
}
end = ktime_get();
printk(KERN_DEBUG "Time taken for function() execution: %llu on cpu %d\n",
ktime_to_ns(ktime_sub(end, start)), CPU_NUM);
return 1;
}
......@@ -231,6 +263,8 @@ static unsigned long beta_connect_mem(struct ipc_container *container,
/* todo talk about this bootstrap issue while we're beta testing */
/* perhaps, we can use extern and export syms? */
container->channel_rx = (struct ttd_ring_channel *) kland;
start = (unsigned long) container->channel_rx->recs;
end = (unsigned long) container->channel_rx->recs + (CHAN_NUM_PAGES * PAGE_SIZE);
return 0;
}
......@@ -272,6 +306,7 @@ static int beta_open(struct inode *nodp, struct file *filep)
return -ENOMEM;
}
container->thread = kthread_create_on_cpu(&ipc_thread_func,
(void *)filep, CPU_NUM,
"betaIPC.%u");
......@@ -293,8 +328,9 @@ static int beta_close(struct inode *nodp, struct file *filep)
container = filep->private_data;
kfree(container);
if (container->channel_tx)
ttd_ring_channel_free(container->channel_tx);
/* if (container->channel_tx)
ttd_ring_channel_free(container->channel_tx);*/
return 0;
......@@ -334,7 +370,7 @@ static long beta_ioctl(struct file *filep, unsigned int cmd,
pr_debug("No such ioctl %d\n", cmd);
break;
}
return 0;
return ret;
}
static const struct file_operations betaIPC_fops = {
......@@ -346,7 +382,7 @@ static const struct file_operations betaIPC_fops = {
static struct miscdevice dev = {
MISC_DYNAMIC_MINOR,
"betaIPC",
"betaIPC2",
&betaIPC_fops,
};
......@@ -356,7 +392,7 @@ static int __init bIPC_init(void)
{
int ret = 0;
CPU_NUM = 0;
CPU_NUM = 3;
if (this_cpu_has(X86_FEATURE_MWAIT))
printk(KERN_DEBUG "HAS MWAIT\n");
......
obj-m := betaModule.o
betaModule-objs := ./ring-chan/ring-channel.o
CFLAGS_betaModule.o = -DDEBUG -DDEBUG_MWAIT_RETRY -g -Wall
obj-m := betaModule1.o
#CFLAGS_betaModule1.o = -DDEBUG -DDEBUG_MWAIT_RETRY -DDEBUG_BOUNDS_CHECK -g -Wall
#CFLAGS_betaModule.o = -DDEBUG -DDEBUG_MWAIT_RETRY -DDEBUG_BOUNDS_CHECK -g -Wall
#CFLAGS_ring-channel.o = -DDEBUG -DDEBUG_MWAIT_RETRY -DDEBUG_BOUNDS_CHECK -g -Wall
CFLAGS_betaModule1.o = -O2
CFLAGS_betaModule.o = -O2
CFLAGS_ring-channel.o = -O2
betaModule1-objs := ./ring-chan/ring-channel.o ./betaModule.o
KDIR := /lib/modules/`uname -r`/build
......
......@@ -12,6 +12,7 @@
#include <asm/mwait.h>
#include <asm/page_types.h>
#include <asm/cpufeature.h>
#include <linux/ktime.h>
#include "ring-chan/ring-channel.h"
#include "betaModule.h"
......@@ -26,6 +27,8 @@ static char *msg = "12345678123456781234567812345678123456781234567812345678" \
"1234567";
static unsigned long start;
static unsigned long end;
/* Stolen and slightly modified from http://rosettacode.org/wiki/Rot-13 */
static char *rot13(char *s, int amount)
......@@ -59,7 +62,7 @@ static void assert_expect_and_zero(struct ipc_message *i_msg, int need_rot)
i_msg->monitor = 0;
}
static inline void monitor_mwait(unsigned long rcx, void *rax,
static inline void monitor_mwait(unsigned long rcx, volatile uint32_t *rax,
unsigned long wait_type)
{
......@@ -80,26 +83,27 @@ static inline void monitor_mwait(unsigned long rcx, void *rax,
mb();
}
local_irq_save(flags);
// local_irq_save(flags);
__monitor((void *)rax, 0, 0);
/* TODO comment for memory barrier, why is this necessary? */
mb();
__mwait(wait_type, rcx);
local_irq_restore(flags);
// local_irq_restore(flags);
}
static inline int trample_imminent(unsigned int *loc)
static inline int trample_imminent(struct ipc_message *loc)
{
return *loc == 0xbadc0de;
return (loc->monitor != 0xC1346BAD) && (loc->monitor != 0);
}
static inline int trample_imminent_store(struct ttd_ring_channel *prod,
unsigned int prod_loc, unsigned int **t_loc)
unsigned int prod_loc, struct ipc_message **t_loc)
{
*t_loc = (unsigned int*) ttd_ring_channel_get_rec_slow(prod, prod_loc);
return ((*(*t_loc)) == 0xbadc0de);
struct ipc_message *imsg;
imsg = (struct ipc_message *) ttd_ring_channel_get_rec_slow(prod, prod_loc);
*t_loc = imsg;
return (imsg->monitor != 0xC1346BAD) && (imsg->monitor != 0);
}
static int ipc_thread_func(void *input)
......@@ -121,6 +125,7 @@ static int ipc_thread_func(void *input)
unsigned int local_prod;
unsigned int *trample_loc;
struct ipc_message *imsg;
ktime_t start, end;
#if defined(DEBUG_MWAIT_RETRY)
unsigned long retry_count = 0;
......@@ -145,33 +150,43 @@ static int ipc_thread_func(void *input)
ttd_ring_channel_set_prod(prod_channel, 1);
ttd_ring_channel_set_cons(prod_channel, 0);
/* 10 mil */
while(count < 10000000) {
start = ktime_get();
while(count < 5000000) {
/* POSSIBLE CACHE THRASHING WILE WAITING ??*/
/* TODO LETS DO BOTH METHODS, LETS MWAIT ON THE NIL */
/* AND LETS MWAIT ONT THE CONSUMER */
if(trample_imminent_store(prod_channel, local_prod, &trample_loc)) {
if(trample_imminent_store(prod_channel, local_prod, &imsg)) {
do{
monitor_mwait(ecx, trample_loc, cstate_wait);
pr_debug("Waiting on CPU %d with %p\n",
CPU_NUM, &imsg->monitor);
monitor_mwait(ecx, &imsg->monitor, cstate_wait);
#if defined(DEBUG_MWAIT_RETRY)
if(retry_count > 50) {
pr_debug("RETRY COUNT FAILED! MORE THAN "\
"50 WAITS on CPU %d\n", CPU_NUM);
pr_err("RETRY COUNT FAILED! MORE THAN"\
"50 WAITS on CPU %d at count %d\n",
CPU_NUM, count);
return -1;
}
retry_count++;
#endif
}while(trample_imminent(trample_loc));
}while(trample_imminent(imsg));
}
/* trample Location is now free for us to write */
imsg = (struct ipc_message *)trample_loc;
memcpy(imsg->message, msg, 63);
imsg->monitor = 0;
ttd_ring_channel_inc_prod(prod_channel);
#if defined (DEBUG_BOUNDS_CHECK)
if((unsigned long)imsg > end || (unsigned long)imsg < start) {
pr_err("OUT OF BOUNDS! with %p\n", trample_loc);
break;
}
#endif
pr_debug("Memcpying in CPU0 iter %d count to loc %p\n",
count, imsg->message);
memcpy(imsg->message, msg, BUF_SIZE);
imsg->monitor = 0xbadbeef;
pr_debug("Wrot to volatile var on CPU %d at loc %p\n",
CPU_NUM, &imsg->monitor);
//ttd_ring_channel_inc_prod(prod_channel);
#if defined(DEBUG_MWAIT_RETRY)
retry_count = 0;
......@@ -179,6 +194,9 @@ static int ipc_thread_func(void *input)
local_prod++;
count++;
}
end = ktime_get();
printk(KERN_DEBUG "Time taken for function() execution: %llu on cpu %d\n",
ktime_to_ns(ktime_sub(end, start)), CPU_NUM);
return 1;
}
......@@ -248,7 +266,13 @@ static unsigned long beta_alloc_mem(struct ipc_container *container)
pr_err("Failed to alloc/Init ring channel\n");
return -ENOMEM;
}
memset(container->channel_tx->rec, 0, (CHAN_NUM_PAGES * PAGE_SIZE));
pr_debug("Channel is at %p, recs are %p to %p\n", (void*)container->channel_tx,
container->channel_tx->recs,
container->channel_tx->recs + (CHAN_NUM_PAGES * PAGE_SIZE));
start = (unsigned long) container->channel_tx->recs;
end = (unsigned long) container->channel_tx->recs + (CHAN_NUM_PAGES * PAGE_SIZE);
memset(container->channel_tx->recs, 0, (CHAN_NUM_PAGES * PAGE_SIZE));
return 0;
}
......@@ -291,11 +315,11 @@ static int beta_close(struct inode *nodp, struct file *filep)
struct ipc_container *container;
container = filep->private_data;
kfree(container);
// container = filep->private_data;
//kfree(container);
if (container->channel_tx)
ttd_ring_channel_free(container->channel_tx);
// if (container->channel_tx)
// ttd_ring_channel_free(container->channel_tx);
return 0;
......@@ -335,7 +359,7 @@ static long beta_ioctl(struct file *filep, unsigned int cmd,
pr_debug("No such ioctl %d\n", cmd);
break;
}
return 0;
return ret;
}
static const struct file_operations betaIPC_fops = {
......
......@@ -2,6 +2,7 @@
int CHAN_NUM_PAGES = 2;
int BUF_SIZE = 28;
struct ipc_container{
struct task_struct *thread;
......@@ -11,7 +12,7 @@ struct ipc_container{
/*Don't let gcc do anything cute, we need this to be 128 bytes */
struct ipc_message{
char message[63];
char message[28];
volatile uint32_t monitor;
}__attribute__((packed));
......
......@@ -15,9 +15,17 @@
#include "ring-channel.h"
static inline unsigned long bsrl(unsigned long x)
{
unsigned long ret;
asm("bsr %1,%0" : "=r"(ret) : "r"(x));
return ret;
}
static inline unsigned long lower_power_of_two(unsigned long x)
{
return 0x80000000000000 >> __builtin_clz(x);
return 0x80000000000000UL >> (__builtin_clzl(x)-1);
}
......@@ -95,9 +103,25 @@ int ttd_ring_channel_alloc_with_metadata(struct ttd_ring_channel *ring_channel,
ttd_ring_channel_reinit_stats(ring_channel->buf);
ring_channel->size_of_a_rec = size_of_a_rec;
ring_channel->size_in_recs = (lower_power_of_two(size_in_pages * PAGE_SIZE))
/ ring_channel->size_of_a_rec;
pr_debug("Size of a rec is %lu\n", size_of_a_rec);
/* ring_channel->size_in_recs = (lower_power_of_two(size_in_pages * PAGE_SIZE))
/ ring_channel->size_of_a_rec;
*/
ring_channel->size_in_recs = (size_in_pages * PAGE_SIZE) /
ring_channel->size_of_a_rec;
pr_debug("size in recs is %lu lower_power_of_two returned %lu and in hex %lxwith input %lu and hex %lx\n",
ring_channel->size_in_recs,
lower_power_of_two(size_in_pages * PAGE_SIZE),
lower_power_of_two(size_in_pages * PAGE_SIZE),
(size_in_pages * PAGE_SIZE), (size_in_pages * PAGE_SIZE));
if (ring_channel->size_in_recs == 0) {
pr_err(" Size_in_recs was incorrectly 0\n");
ret = -EINVAL; goto cleanup;
}
/* Init shared buffer structures */
......
......@@ -17,13 +17,13 @@
#define printf_v(fmt, ...) \
if(verbose) \
printf(fmt,##__VA_ARGS__);
static int verbose;
static int open_beta_drivers(int* beta1, int* beta2)
{
printf_v("[*] Opening \"betaIPC\"\n");
*beta1 = open("/dev/betaIPC", O_RDWR);
......@@ -80,14 +80,14 @@ static int connect_mem_regions(int fd2, unsigned long *ptr)
static int unpark_threads(int fd, int fd2)
{
long ret = -1;
ret = ioctl(fd2, BETA_UNPARK_THREAD, NULL);
if(ret != 0) {
printf("Couldn't unpark beta2!\n");
return 1;
}
printf_v("[*] Woke up CPU3 waking up CPU 0\n");
printf_v("[*] Woke up CPU0 waking up CPU3\n");
ret = ioctl(fd, BETA_UNPARK_THREAD, NULL);
if(ret != 0) {
printf("Couldn't unpark beta1!\n");
......
Markdown is supported
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