Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
X
xcap-ipc-module
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
xcap
xcap-ipc-module
Commits
9340e277
Commit
9340e277
authored
Feb 04, 2015
by
Scotty Bauer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
integration complete
Signed-off-by:
Scott Bauer
<
sbauer@eng.utah.edu
>
parent
0788356e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
233 additions
and
230 deletions
+233
-230
kernel/Makefile
kernel/Makefile
+3
-2
kernel/betaModule.c
kernel/betaModule.c
+122
-139
kernel/betaModule.h
kernel/betaModule.h
+7
-4
kernel/ring-chan/ring-channel.c
kernel/ring-chan/ring-channel.c
+15
-9
kernel/ring-chan/ring-channel.h
kernel/ring-chan/ring-channel.h
+86
-76
No files found.
kernel/Makefile
View file @
9340e277
obj-m
:=
betaModule.o
CFLAGS_betaModule.o
=
-DDEBUG
-g
-O2
-Wall
obj-m
:=
betaModule.o
betaModule-objs
:=
./ring-chan/ring-channel.o
CFLAGS_betaModule.o
=
-DDEBUG
-DDEBUG_MWAIT_RETRY
-g
-Wall
KDIR
:=
/lib/modules/
`
uname
-r
`
/build
...
...
kernel/betaModule.c
View file @
9340e277
...
...
@@ -13,73 +13,19 @@
#include <asm/page_types.h>
#include <asm/cpufeature.h>
#include "ring-chan/ring-channel.h"
#include "betaModule.h"
MODULE_LICENSE
(
"GPL"
);
/**
* Useful things to look at:
* wait_event_interruptible /wait.h
* alloc_page / gfp.h
* http://lxr.free-electrons.com/source/arch/x86/include/asm/mwait.h#L26
*
*/
/** TODO and THOUGHTS
*
* TODO: Move kthread creation into open so we can install
* In filp->private_data? -- Think about context of
* who calls this code... It's coming from kland?
*
* TODO: Mutex on current_avail_token and the array of mem_tokens
* TODO: will atomic inc work for cur_avail_token?
*/
static
const
int
CPU_NUM
;
static
int
CPU_NUM
;
/* 124 byte message */
static
char
*
msg
=
"The quick brown fox jumped over the lazy dog."
\
"Sally sells sea shells down by the sea shore. abcdefghijkl"
\
"mnopqrstuvwxyz12345"
;
static
char
*
msg
=
"12345678123456781234567812345678123456781234567812345678"
\
"1234567"
;
static
inline
int
keep_waiting
(
struct
ipc_message
*
i_msg
,
unsigned
int
notify_key
)
{
return
!
(
i_msg
->
monitor
==
notify_key
);
}
static
void
send_and_notify
(
struct
ipc_message
*
i_msg
,
char
*
_msg
,
size_t
len
,
unsigned
int
notify_key
)
{
memcpy
(
i_msg
->
message
,
_msg
,
len
);
/*pr_debug("BETA %d WRITING TO VOLTAILE VAR AT %p\n", CPU_NUM,
&i_msg->monitor);*/
i_msg
->
monitor
=
notify_key
;
}
static
inline
void
*
get_current_slot
(
size_t
offset
,
void
*
buf
)
{
return
(
void
*
)
((
char
*
)
buf
+
offset
);
}
/* All the casts are in here to stick within the standard.
* 6.2.5-19: The void type comprises an empty set of values;
* it is an incomplete type that cannot be completed.
*/
static
inline
void
*
get_next_slot
(
size_t
*
offset
,
void
*
buf
)
{
*
offset
+=
sizeof
(
struct
ipc_message
);
*
offset
%=
(
PAGE_SIZE
*
2
);
return
(
void
*
)
((
char
*
)
buf
)
+
*
offset
;
}
/* Stolen and slightly modified from http://rosettacode.org/wiki/Rot-13 */
static
char
*
rot13
(
char
*
s
,
int
amount
)
...
...
@@ -113,38 +59,49 @@ static void assert_expect_and_zero(struct ipc_message *i_msg, int need_rot)
i_msg
->
monitor
=
0
;
}
static
void
___monitor
(
const
void
*
eax
,
unsigned
long
ecx
,
unsigned
long
edx
)
{
/* "monitor %eax, %ecx, %edx;" */
asm
volatile
(
".byte 0x0f, 0x01, 0xc8;"
:
:
"a"
(
eax
),
"c"
(
ecx
),
"d"
(
edx
));
}
static
void
___mwait
(
unsigned
long
eax
,
unsigned
long
ecx
)
{
/* "mwait %eax, %ecx;" */
asm
volatile
(
".byte 0x0f, 0x01, 0xc9;"
:
:
"a"
(
eax
),
"c"
(
ecx
));
}
static
inline
void
monitor_mwait
(
unsigned
long
rcx
,
volatile
void
*
rax
,
static
inline
void
monitor_mwait
(
unsigned
long
rcx
,
void
*
rax
,
unsigned
long
wait_type
)
{
unsigned
long
flags
;
int
cpu
;
/* TODO Figure out wtf the "extensions" and "hints" do for monitor */
if
(
this_cpu_has
(
X86_BUG_CLFLUSH_MONITOR
))
wbinvd
();
/* smp is supposed to be used under "lock", however one can use it if
* you have pegged your thread to a CPU, which we have.
*/
cpu
=
smp_processor_id
();
if
(
cpu_has_bug
(
&
cpu_data
(
cpu
),
X86_BUG_CLFLUSH_MONITOR
))
{
mb
();
clflush
(
rax
);
mb
();
}
local_irq_save
(
flags
);
__
_
monitor
((
void
*
)
rax
,
0
,
0
);
__monitor
((
void
*
)
rax
,
0
,
0
);
/* TODO comment for memory barrier, why is this necessary? */
smp_
mb
();
__
_
mwait
(
wait_type
,
rcx
);
mb
();
__mwait
(
wait_type
,
rcx
);
local_irq_restore
(
flags
);
}
static
inline
int
trample_imminent
(
unsigned
int
*
loc
)
{
return
*
loc
==
0xbadc0de
;
}
static
inline
int
trample_imminent_store
(
struct
ttd_ring_channel
*
prod
,
unsigned
int
prod_loc
,
unsigned
int
**
t_loc
)
{
*
t_loc
=
(
unsigned
int
*
)
ttd_ring_channel_get_rec_slow
(
prod
,
prod_loc
);
return
((
*
(
*
t_loc
))
==
0xbadc0de
);
}
static
int
ipc_thread_func
(
void
*
input
)
{
/* This will be a while true loop with timing code and mwaits
...
...
@@ -155,15 +112,19 @@ static int ipc_thread_func(void *input)
byte boundary until it gets out of its OPT loop
*/
struct
file
*
filep
=
input
;
struct
file
*
filep
=
input
;
struct
ipc_container
*
container
=
NULL
;
unsigned
long
ecx
=
1
;
/*break of interrupt flag */
unsigned
long
cstate_wait
=
2
;
size_t
offset
=
0
;
void
*
buf
;
struct
ipc_message
*
overlay
;
struct
ttd_ring_channel
*
prod_channel
;
int
count
=
0
;
int
retry_count
=
0
;
unsigned
int
local_prod
;
unsigned
int
*
trample_loc
;
struct
ipc_message
*
imsg
;
#if defined(DEBUG_MWAIT_RETRY)
unsigned
long
retry_count
=
0
;
#endif
if
(
filep
==
NULL
)
{
pr_debug
(
"Thread was sent a null filepointer!
\n
"
);
...
...
@@ -172,49 +133,55 @@ static int ipc_thread_func(void *input)
container
=
filep
->
private_data
;
if
(
container
==
NULL
&&
container
->
mem_size
==
0
)
{
if
(
container
==
NULL
&&
container
->
channel_rx
==
NULL
)
{
pr_debug
(
"container was null in thread!
\n
"
);
return
-
EINVAL
;
}
buf
=
container
->
mem_start
;
/* setup hi-res timers */
pr_debug
(
"Hello from thread in CPU %d
\n
"
,
CPU_NUM
);
if
(
CPU_NUM
==
0
)
{
while
(
count
<
1000000
)
{
/* we send first */
overlay
=
get_current_slot
(
offset
,
buf
);
send_and_notify
(
overlay
,
msg
,
124
,
0xdeadbeef
);
overlay
=
get_next_slot
(
&
offset
,
buf
);
/* mwait on response location */
/*pr_debug("BETA %d WAITING ON MONITOR, at %p\n",
CPU_NUM, &overlay->monitor);*/
/* TIME ON */
retry:
monitor_mwait
(
ecx
,
&
overlay
->
monitor
,
cstate_wait
);
/*TIME OFF!*/
if
(
keep_waiting
(
overlay
,
0xbadc0de
)
&&
retry_count
<
150
)
{
prod_channel
=
container
->
channel_tx
;
/* PRODUCER */
local_prod
=
1
;
ttd_ring_channel_set_prod
(
prod_channel
,
1
);
ttd_ring_channel_set_cons
(
prod_channel
,
0
);
/* 10 mil */
while
(
count
<
10000000
)
{
/* 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
))
{
do
{
monitor_mwait
(
ecx
,
trample_loc
,
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
);
return
-
1
;
}
retry_count
++
;
/*pr_debug("Retrying with count %d on CPU %d\n",
retry_count, CPU_NUM);*/
goto
retry
;
}
else
if
(
retry_count
>
150
)
{
printk
(
KERN_DEBUG
"TERMINATING EARLY ON CPU %d
\n
"
,
CPU_NUM
);
break
;
}
assert_expect_and_zero
(
overlay
,
1
);
memset
(
overlay
->
message
,
0
,
124
);
get_next_slot
(
&
offset
,
buf
);
#endif
}
while
(
trample_imminent
(
trample_loc
));
/* 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_MWAIT_RETRY)
retry_count
=
0
;
count
++
;
}
pr_debug
(
"Complete on %d
\n
"
,
CPU_NUM
);
#endif
}
local_prod
++
;
count
++
;
}
return
0
;
return
1
;
}
static
inline
unsigned
long
beta_ret_cpu
(
unsigned
long
__arg
)
...
...
@@ -228,7 +195,7 @@ static inline unsigned long beta_ret_cpu(unsigned long __arg)
static
unsigned
long
beta_unpark_thread
(
struct
ipc_container
*
container
)
{
if
(
container
->
thread
==
NULL
||
container
->
mem_size
==
0
)
if
(
container
->
thread
==
NULL
)
return
-
EINVAL
;
/* FROM THIS POINT FORWARD, ATLEAST ONE OF THE THREADS
...
...
@@ -259,41 +226,52 @@ static unsigned long beta_connect_mem(struct ipc_container *container,
kland
=
(
unsigned
long
*
)
kland_real
;
if
(
kland
!=
NULL
&&
*
kland
!=
0xdeadbeef
)
if
(
kland
==
NULL
)
return
-
EFAULT
;
container
->
mem_start
=
kland
;
container
->
mem_size
=
PAGE_SIZE
*
2
;
/* 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
;
return
0
;
}
static
unsigned
long
beta_alloc_mem
(
struct
ipc_container
*
container
)
{
if
(
container
->
mem_size
>
0
)
return
0
;
container
->
mem_start
=
kzalloc
((
PAGE_SIZE
*
2
),
GFP_KERNEL
);
if
(
!
container
->
mem_start
)
return
-
1
;
int
ret
;
if
(
container
->
channel_tx
==
NULL
)
return
-
EINVAL
;
container
->
mem_size
=
PAGE_SIZE
*
2
;
ret
=
ttd_ring_channel_alloc
(
container
->
channel_tx
,
CHAN_NUM_PAGES
,
sizeof
(
struct
ipc_message
));
/* Yes I know this is outright disgusting */
*
((
unsigned
long
*
)
container
->
mem_start
)
=
0xdeadbeef
;
if
(
ret
!=
0
)
{
pr_err
(
"Failed to alloc/Init ring channel
\n
"
);
return
-
ENOMEM
;
}
return
0
;
}
static
int
beta_open
(
struct
inode
*
nodp
,
struct
file
*
filep
)
{
/* setup kernel thread, bound to some CPU, but do not run */
struct
ipc_container
*
container
;
container
=
kzalloc
(
sizeof
(
*
container
),
GFP_KERNEL
);
if
(
!
container
)
{
pr_debug
(
"Could not alloc space for container
\n
"
);
return
-
1
;
pr_err
(
"Could not alloc space for container
\n
"
);
return
-
ENOMEM
;
}
container
->
channel_tx
=
kzalloc
(
sizeof
(
*
container
->
channel_tx
),
GFP_KERNEL
);
if
(
!
container
->
channel_tx
)
{
pr_err
(
"Could not alloc space for ring channel
\n
"
);
return
-
ENOMEM
;
}
container
->
thread
=
kthread_create_on_cpu
(
&
ipc_thread_func
,
...
...
@@ -301,7 +279,7 @@ static int beta_open(struct inode *nodp, struct file *filep)
"betaIPC.%u"
);
if
(
IS_ERR
(
container
->
thread
))
{
pr_
debug
(
"Error while creating kernel thread
\n
"
);
pr_
err
(
"Error while creating kernel thread
\n
"
);
return
PTR_ERR
(
container
->
thread
);
}
...
...
@@ -311,11 +289,16 @@ static int beta_open(struct inode *nodp, struct file *filep)
static
int
beta_close
(
struct
inode
*
nodp
,
struct
file
*
filep
)
{
/* TODO STOP LEAKING 2 PAGES OF MEMORY FROM THE CONTAINER!\n */
struct
ipc_container
*
container
;
container
=
filep
->
private_data
;
kfree
(
container
);
if
(
container
->
channel_tx
)
ttd_ring_channel_free
(
container
->
channel_tx
);
return
0
;
}
...
...
@@ -324,7 +307,7 @@ static long beta_return_mem(struct ipc_container *container,
{
unsigned
long
__user
*
save
=
(
unsigned
long
*
)
__arg
;
return
put_user
((
unsigned
long
)
container
->
mem_start
,
save
);
return
put_user
((
unsigned
long
)
container
->
channel_tx
,
save
);
}
static
long
beta_ioctl
(
struct
file
*
filep
,
unsigned
int
cmd
,
...
...
kernel/betaModule.h
View file @
9340e277
#include <linux/types.h>
int
CHAN_NUM_PAGES
=
2
;
struct
ipc_container
{
struct
task_struct
*
thread
;
s
ize_t
mem_size
;
void
*
mem_start
;
s
truct
ttd_ring_channel
*
channel_tx
;
struct
ttd_ring_channel
*
channel_rx
;
};
/*Don't let gcc do anything cute, we need this to be 128 bytes */
struct
ipc_message
{
char
message
[
124
];
struct
ipc_message
{
char
message
[
63
];
volatile
uint32_t
monitor
;
}
__attribute__
((
packed
));
...
...
kernel/ring-chan/ring-channel.c
View file @
9340e277
...
...
@@ -11,10 +11,11 @@
#include <asm-generic/getorder.h>
#include <linux/mm.h>
#include <linux/gfp.h>
#include "ring-channel.h"
static
inline
unsigned
long
lower_power_of_two
(
unsigned
long
)
static
inline
unsigned
long
lower_power_of_two
(
unsigned
long
x
)
{
return
0x80000000000000
>>
__builtin_clz
(
x
);
}
...
...
@@ -40,12 +41,14 @@ int ttd_ring_channel_alloc(struct ttd_ring_channel *ring_channel,
void
ttd_ring_channel_free
(
struct
ttd_ring_channel
*
ring_channel
)
{
if
(
ring_channel
->
recs
)
{
free_pages
((
void
*
)
ring_channel
->
recs
,
ring_channel
->
buf_order
);
free_pages
((
unsigned
long
)
ring_channel
->
recs
,
ring_channel
->
buf_order
);
ring_channel
->
recs
=
NULL
;
}
if
(
ring_channel
->
buf
)
{
free_pages
((
void
*
)
ring_channel
->
buf
,
ring_channel
->
header_order
);
free_pages
((
unsigned
long
)
ring_channel
->
buf
,
ring_channel
->
header_order
);
ring_channel
->
buf
=
NULL
;
}
}
...
...
@@ -57,9 +60,8 @@ int ttd_ring_channel_alloc_with_metadata(struct ttd_ring_channel *ring_channel,
unsigned
long
priv_metadata_size
)
{
int
ret
;
unsigned
long
order
,
header_order
,
i
;
unsigned
long
order
,
header_order
;
unsigned
long
size_of_header_in_pages
;
pr_debug
(
"Allocating ring channel
\n
"
);
ttd_ring_channel_init
(
ring_channel
);
...
...
@@ -69,7 +71,7 @@ int ttd_ring_channel_alloc_with_metadata(struct ttd_ring_channel *ring_channel,
sizeof
(
struct
ttd_buf
));
if
(
(
ring_channel
->
buf
=
__get_free_pages
(
GFP_KERNEL
,
header_order
))
==
NULL
)
{
if
(
(
ring_channel
->
buf
=
(
void
*
)
__get_free_pages
(
GFP_KERNEL
,
header_order
))
==
NULL
)
{
pr_err
(
"Xen deterministic time-travel buffers: memory allocation failed
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -80,8 +82,8 @@ int ttd_ring_channel_alloc_with_metadata(struct ttd_ring_channel *ring_channel,
priv_metadata_size
+
sizeof
(
struct
ttd_buf
),
size_of_header_in_pages
);
order
=
get_order_from_pages
(
size_in_pages
);
if
(
(
ring_channel
->
recs
=
__get_free_pages
(
GFP_KERNEL
,
order
))
==
NULL
)
{
pr_er
(
"Xen deterministic time-travel buffers: memory allocationcd failed, "
if
(
(
ring_channel
->
recs
=
(
char
*
)
__get_free_pages
(
GFP_KERNEL
,
order
))
==
NULL
)
{
pr_er
r
(
"Xen deterministic time-travel buffers: memory allocationcd failed, "
"size in pages:%lu, order:%lu
\n
"
,
size_in_pages
,
order
);
ret
=
-
EINVAL
;
goto
cleanup
;
}
...
...
@@ -98,7 +100,11 @@ int ttd_ring_channel_alloc_with_metadata(struct ttd_ring_channel *ring_channel,
/* Init shared buffer structures */
ring_channel
->
buf
->
payload_buffer_mfn
=
ring_channel
->
recs
;
/*NOTE*/
ring_channel
->
buf
->
payload_buffer_mfn
=
(
unsigned
long
)
ring_channel
->
recs
;
/*NOTE*/
ring_channel
->
buf
->
payload_buffer_size
=
size_in_pages
*
PAGE_SIZE
;
ring_channel
->
buf
->
size_of_a_rec
=
ring_channel
->
size_of_a_rec
;
...
...
kernel/ring-chan/ring-channel.h
View file @
9340e277
...
...
@@ -12,10 +12,10 @@
*
*/
#ifndef __XEN_RING_CHANNEL_H__
#ifndef __XEN_RING_CHANNEL_H__
#define __XEN_RING_CHANNEL_H__
#include <string.h>
#include <
linux/
string.h>
/*
...
...
@@ -23,85 +23,85 @@
* field, indexes into an array of struct t_rec's.
*/
struct
ttd_buf
{
unsigned
long
cons
;
/* Next item to be consumed by control tools. */
unsigned
long
prod
;
/* Next item to be produced by Xen. */
unsigned
long
cons
;
/* Next item to be consumed by control tools. */
unsigned
long
prod
;
/* Next item to be produced by Xen. */
/* Shape of the buffer */
unsigned
long
payload_buffer_mfn
;
unsigned
long
payload_buffer_size
;
/* Shape of the buffer */
unsigned
long
payload_buffer_mfn
;
unsigned
long
payload_buffer_size
;
unsigned
long
size_of_a_rec
;
/* size of a single record */
unsigned
long
size_of_a_rec
;
/* size of a single record */
unsigned
long
size_in_recs
;
/* size of the buffer in recs */
unsigned
long
size_in_recs
;
/* size of the buffer in recs */
/* Stats for the buffer */
/* Stats for the buffer */
unsigned
long
long
avg_queue_size
;
/* average size of the request queue in the buffer */
unsigned
long
long
msgs_sent
;
/* total number of messages sent */
unsigned
long
msgs_by_type
[
128
];
/* count how many messages of individual type we record */
unsigned
long
long
tx_notifications
;
/* total number of TX notifications */
unsigned
long
long
tx_hit_emergency_margin
;
/* total number of times the channel gets emergently full */
unsigned
long
long
rx_notifications
;
/* total number of RX notifications */
unsigned
long
long
msgs_with_extra_reg_space
;
/* total number of messages which asked for extra space in registers */
unsigned
long
msgs_with_extra_reg_space_by_type
[
128
];
/* count how many times an individual event type asks for more space */
unsigned
long
long
msgs_with_extra_data_space
;
/* total number of messages which asked for extra space for data */
unsigned
long
msgs_with_extra_data_space_by_type
[
128
];
/* count how many times an individual event type asks for more space */
unsigned
long
long
avg_queue_size
;
/* average size of the request queue in the buffer */
unsigned
long
long
msgs_sent
;
/* total number of messages sent */
unsigned
long
msgs_by_type
[
128
];
/* count how many messages of individual type we record */
unsigned
long
long
tx_notifications
;
/* total number of TX notifications */
unsigned
long
long
tx_hit_emergency_margin
;
/* total number of times the channel gets emergently full */
unsigned
long
long
rx_notifications
;
/* total number of RX notifications */
unsigned
long
long
msgs_with_extra_reg_space
;
/* total number of messages which asked for extra space in registers */
unsigned
long
msgs_with_extra_reg_space_by_type
[
128
];
/* count how many times an individual event type asks for more space */
unsigned
long
long
msgs_with_extra_data_space
;
/* total number of messages which asked for extra space for data */
unsigned
long
msgs_with_extra_data_space_by_type
[
128
];
/* count how many times an individual event type asks for more space */
/* 'ttd_nr_recs' records follow immediately after the meta-data header. */
/* 'ttd_nr_recs' records follow immediately after the meta-data header. */
};
struct
ttd_ring_channel
{
struct
ttd_buf
*
buf
;
/* pointer to the buffer metadata */
unsigned
long
buf_mfn
;
unsigned
long
buf_order
;
struct
ttd_buf
*
buf
;
/* pointer to the buffer metadata */
unsigned
long
buf_mfn
;
unsigned
long
buf_order
;
void
*
priv_metadata
;
/* pointer to the private buffer metadata */
unsigned
long
priv_metadata_size
;
/* size of the private buffer metadata */
unsigned
long
header_order
;
/* size of the private buffer metadata */
void
*
priv_metadata
;
/* pointer to the private buffer metadata */
unsigned
long
priv_metadata_size
;
/* size of the private buffer metadata */
unsigned
long
header_order
;
/* size of the private buffer metadata */
char
*
recs
;
/* pointer to buffer data areas */
char
*
recs
;
/* pointer to buffer data areas */
unsigned
long
size_of_a_rec
;
/* size of a single record */
unsigned
long
size_of_a_rec
;
/* size of a single record */
unsigned
long
size_in_recs
;
/* size of the buffer in recs */
unsigned
long
size_in_recs
;
/* size of the buffer in recs */
unsigned
long
highwater
;
/* buffer is quite full, time to notify other end */
unsigned
long
emergency_margin
;
/* buffer is nearly full, time to freeze everything */
unsigned
long
highwater
;
/* buffer is quite full, time to notify other end */
unsigned
long
emergency_margin
;
/* buffer is nearly full, time to freeze everything */
};
static
inline
void
ttd_ring_channel_reinit_stats
(
struct
ttd_buf
*
buf
)
{
buf
->
avg_queue_size
=
;
0
buf
->
msgs_sent
=
0
;
buf
->
tx_notifications
=
0
;
buf
->
rx_notifications
=
0
;
buf
->
tx_hit_emergency_margin
=
0
;
buf
->
msgs_with_extra_reg_space
=
0
;
buf
->
msgs_with_extra_data_space
=
0
;
memset
(
buf
->
msgs_by_type
,
0
,
sizeof
(
buf
->
msgs_by_type
));
memset
(
buf
->
msgs_with_extra_reg_space_by_type
,
0
,
sizeof
(
buf
->
msgs_with_extra_reg_space_by_type
));
memset
(
buf
->
msgs_with_extra_data_space_by_type
,
0
,
sizeof
(
buf
->
msgs_with_extra_data_space_by_type
));
buf
->
avg_queue_size
=
0
;
buf
->
msgs_sent
=
0
;
buf
->
tx_notifications
=
0
;
buf
->
rx_notifications
=
0
;
buf
->
tx_hit_emergency_margin
=
0
;
buf
->
msgs_with_extra_reg_space
=
0
;
buf
->
msgs_with_extra_data_space
=
0
;
memset
(
buf
->
msgs_by_type
,
0
,
sizeof
(
buf
->
msgs_by_type
));
memset
(
buf
->
msgs_with_extra_reg_space_by_type
,
0
,
sizeof
(
buf
->
msgs_with_extra_reg_space_by_type
));
memset
(
buf
->
msgs_with_extra_data_space_by_type
,
0
,
sizeof
(
buf
->
msgs_with_extra_data_space_by_type
));
}
static
inline
void
ttd_ring_channel_init
(
struct
ttd_ring_channel
*
ring_channel
)
{
memset
(
ring_channel
,
0
,
sizeof
(
*
ring_channel
));
return
;
memset
(
ring_channel
,
0
,
sizeof
(
*
ring_channel
));
return
;
}
static
inline
void
ttd_ring_channel_buf_init
(
struct
ttd_buf
*
buf
)
{
memset
(
buf
,
0
,
sizeof
(
*
buf
));
return
;
memset
(
buf
,
0
,
sizeof
(
*
buf
));
return
;
}
int
ttd_ring_channel_alloc
(
struct
ttd_ring_channel
*
ring_channel
,
...
...
@@ -115,67 +115,77 @@ int ttd_ring_channel_alloc_with_metadata(struct ttd_ring_channel *ring_channel,
void
ttd_ring_channel_free
(
struct
ttd_ring_channel
*
ring_channel
);
static
inline
void
*
ttd_ring_channel_get_priv_metadata
(
struct
ttd_ring_channel
*
ring_channel
)
static
inline
void
*
ttd_ring_channel_get_priv_metadata
(
struct
ttd_ring_channel
*
ring_channel
)
{
return
ring_channel
->
priv_metadata
;
return
ring_channel
->
priv_metadata
;
}
static
inline
unsigned
long
ttd_ring_channel_get_prod
(
struct
ttd_ring_channel
*
ring_channel
)
{
return
ring_channel
->
buf
->
prod
;
static
inline
unsigned
long
ttd_ring_channel_get_prod
(
struct
ttd_ring_channel
*
ring_channel
)
{
return
ring_channel
->
buf
->
prod
;
};
static
inline
unsigned
long
ttd_ring_channel_inc_prod
(
struct
ttd_ring_channel
*
ring_channel
)
{
return
(
ring_channel
->
buf
->
prod
++
);