How should I be mixing RCU reader and updater code? - linux

I have a boilerplate function that finds a structure in a tree-like database:
struct foo {
struct foo *child1; /* RCU-protected. */
struct foo *child2; /* RCU-protected. */
... /* Other stuff */
}
static struct foo *find_foo(int arg)
{
struct foo *parent;
... /* Do something to find parent. */
return rcu_dereference(parent->child1); /* or child2. Whatever. */
}
And then I have several functions that do something with that result:
void a(int arg)
{
struct foo *bar;
rcu_read_lock();
bar = find_foo(arg);
... /* Read something from bar and do something with it. */
rcu_read_unlock();
}
And then I have a single updater/reclaimer. It needs to find the object just like the "a" functions (Assume it's already mutex'd from outside):
void c(int arg)
{
struct foo *bar;
bar = find_foo(arg);
... /* make a backup pointer of bar->child1. */
rcu_assign_pointer(bar->child1, ...);
... /* free the old child or whatever. */
}
My problem is, rcu_dereference()'s documentation says it must be called from within a read-side critical section (ie. between rcu_read_lock() and rcu_read_unlock()). c() violates this rule by calling find_foo().
I'm hesitant to make a whole new version of find_foo() which uses rcu_dereference_protected() instead of rcu_dereference(), because it's too much duplicate code, so I'm wondering if this implementation of c() is legal:
void c(int arg)
{
struct foo *bar;
rcu_read_lock();
bar = find_foo(arg);
bar = rcu_dereference_protected(bar, ...); /* THIS. */
rcu_read_unlock();
... /* make a backup pointer of bar->child1. */
rcu_assign_pointer(bar->child1, ...);
... /* free the old child or whatever. */
}
If this is not legal, how should I instead be mixing reader and updater code?

Actually, the first variant of c() is correct (no specific dereference is needed on updater side), but it makes rcu checker to be confused (the checker expects rcu_dereference occured under rcu_read section).
The second variant of c() is correct even from the view of rcu checker, but rcu_dereference_protected is not need: bar is already result of rcu_dereference.
Another way for make rcu checker happy is to use
rcu_dereference_check(<pointer>, <condition-when-in-updater>)
instead of
rcu_dereference(<pointer>)
inside foo implementation. So checker will not complain on foo() call outside of rcu_read section until it can prove that condition is false in that case.
With such foo() implementation the first variant of c() is OK.

Related

EXPORT_SYMBOL a dynamic memory location

Is it possible to EXPORT_SYMBOL() a struct that contains a kmalloc array? If yes, what are the things that I need to keep in mind?
This is a psuedo code of what I want to do.
struct test {
int a;
...
uint64_t* data;
}
struct test foo;
EXPORT_SYMBOL(foo);
...
In module1_kthread1_func() I have:
int module1_kthread1_func(void *foo){
...
foo->data = kmalloc(SIZE, GFP_KERNEL);
...
foo->data[var] = 1243;
var++;
...
}
In module2_kthread2_func() I have:
...
extern struct test foo;
...
int module2_kthread2_func(void* foo){
...
for (i=0; i<SIZE; i++)
printk(KERN_INFO "Variable value of %d is %llu", i, foo->data[var]);
...
}
It's definitely possible, yes.
You need to be careful and make sure that code that uses it knows that some of the fields might not be available before they are allocated. That is, check if they are NULL first instead of directly accessing them.
You might want to declare the structure with an explicit initializer, just so that it is obvious what is going on:
struct test foo = {
.a = 123,
.data = NULL // Initialized by function X when Y
};
EXPORT_SYMBOL(foo);
If such fields are compulsory for the structure to be used, you might want to initialize them early on (see here).

CANoe CAPL struct initialization

I'm having trouble with declaration and initialization of a struct in Vectors CANoe CAPL. I already know structs from C/C++ but it seems the declaration is a little different in CAPL.
The Vector help function isn't really revealing.
I have a number of CAN IDs (e.g. 0x61A). Every CAN ID is a different number of Signal IDs (e.g. 0xDDF6) assigned. I want to read out cyclic the Signal ID from the CAN IDs and plan to organize this in a convoluted struct.
I already tried out different types of declaration and initialization but every time I get a parse error.
Can you please give me a helping hand for my problem?
Any other ideas to organize my values unlike a struct?
Thank you and regards!
From the CAPL documentation:
Structured types can be declared in CAPL in a similar way to C...
... they may only be used in CAPL programs with CANoe from version 7.0 Service Pack 3.
Example:
variables
{
/* declarating a struct */
struct MyData {
int i;
float f;
};
}
on start
{
/* defining a struct variable and initiliazing the elements */
struct MyData data = {
i = 42,
f = 1.32
};
/* accessing the struct elements */
write("i=%d, f=%f", data.i, data.f);
}
Output:
i=42, f=1.320000
I had a flaw in struct access. Tried to initialize the struct paramters right in the variable declaration routine, not in the on startroutine.
Working code for my multiple data access is now:
variables
{
struct Veh_Database
{
dword ECU;
dword ParamID[8][2];
};
struct Veh_Database ECU_Info[12];
}
on start
{
ECU_Info[0].ECU = 0x1A;
ECU_Info[0].ParamID[0][0] = 0xDD;
ECU_Info[0].ParamID[0][1] = 0xF6;
/* ... */
ECU_Info[1].ECU = 0x12;
ECU_Info[1].ParamID[0][0] = 0xDE;
ECU_Info[1].ParamID[0][1] = 0x9C;
/* ... */
}
Thanks for your help!
Just for completeness: It is also possible to initialize a struct in the variable declaration:
variables
{
struct myStruct
{
dword val;
dword arr[8];
};
struct myStruct myInstance = {1, {1,2,3,4,5,6,7,8}};
}
(tested on CANoe 10)
CAPL allows initialization of variables structures at declaration also at Onstart procedure but we have to follow correct syntax. here is example code
variables
{
struct mydata
{
int a;
int b;
} ak={5,3};
}
on start
{
write("Initial values are %d, %d",ak.a,ak.b);
ak.a=10;
ak.b=20;
write("values after update are %d, %d", ak.a,ak.b);
}
find more details in following video
https://www.youtube.com/watch?v=hRfSqZBZVHA

Why do CORBA interfaces have a return type and an out keyword?

I was reading about CORBA and I noticed something funny. CORBA interface methods are defined with a return type, for example string in
module HelloApp
{
interface Hello
{
string sayHello();
oneway void shutdown();
};
};
and also has a keyword out which when passed as a parameter, means that value is returned. For example here
struct Data { ... };
typedef sequence<Data> DataSeq;
interface DataIterator {
DataSeq next_n_items(in unsigned long how_many);
void destroy();
};
interface SearchEngine {
DataSeq query(
in string search_condition,
in unsigned long how_many,
out DataSeq results,
out DataIterator iter);
};
Seems redundant. Why do you need both?
An operation can only have one return value, but can have a multiple out arguments. It is a user decision what to use, but in a lot of cases an operation returns one value and then it is easier for the user to have a return value so that he can write for example (using IDL to C++11):
int32_t my_result = foo->my_operation ();
Where with an out argument he has to write
int32_t my_result {};
foo->my_operation (my_result);
The first example is easier and also safer, no need to explicitly initialize my_result to its default value.

Protect struct-pointer from getting garbage collected when passed to an unmanaged dll

Dummy-code to illustrate:
foo.h
[...]
[StructLayout(LayoutKind::Sequential)]
public value struct Bar
{
int in;
string str;
};
Foo(String^ string);
private:
Bar *bar;
foo.cpp
[...]
[DllImport("dummy")]
int _stdcall Baz(Bar *bar, [MarshalAs(UnmanagedType::LPStr)]String ^str);
Foo::Foo(String ^str)
{
bar = new Bar;
if (bar != nullptr)
{
if (!Baz(bar, str))
{
delete bar;
bar= nullptr;
}
}
}
The error occurs sporadically, what happens is that bar is null when Baz gets called, which I assume is due to it getting garbage collected while the code that runs inside the dll is excecuted.
So far I've tried reading up on pin_ptr etc, but I can't find any good resources on how to use it, and when I try to declare the member variable to be a pin_ptr-type, I get an error saying that it can't be a class member.
I'm quite lost, if anyone can tell me how to fix it, why it needs fixing and how the fix works, that'd be great.
edit:
Further info; Baz is only one of many imported dll-methods used, almost every one of the uses the same parameters though, meaning that the first on is Bar *bar, followed by other parameters which are passed into the wrapper function.

Do you need to call init_timer() again after a del_timer()

I have a Linux module which creates timers, some of which may add themselves again during their handler function.
In some other cases, the timer is removed (perhaps before it's gone off) using del_timer_sync().
In that case, do I need to do the init_timer() call again on the struct before I next add_timer() or is that just a waste of (precious) interrupt latency?
To answer my own question, I believe I do need to init_timer() my struct after any del_timer() or del_timer_sync() if I ever intend to access the struct again - for example, when doing a timer_pending() or something during module cleanup.
I think in the case of writing a kernel module which potentially re-uses a timer, the best thing to do is:
static struct timer_list my_timer;
...
static void remove_my_timer(void)
{
if (timer_pending(&my_timer))
{
del_timer_sync(&my_timer);
init_timer(&my_timer);
}
}
static void arm_my_timer(...)
{
remove_my_timer();
my_timer.expires = ...;
my_timer.data = ...;
my_timer.function = ...;
add_timer(&my_timer);
}
...
int __init init_my_device(void)
{
...
init_timer(&my_timer);
...
}
void __exit cleanup_my_device(void)
{
...
remove_my_timer();
...
}
Hope that helps someone else in future.

Resources