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).
Related
I coded an Arduino project for my son and learned about C in the process. All works fine but after dividing up the code into ten files and grouping the variables into structs in each file I'm not able to solve one wish for clarity. We need to empirically determine the best size of an array for storing and averaging port reads so this is what I want:
struct Alarms {
// Configurable parameters
const unsigned int number_of_reads = 24;
// State variables
int reads[number_of_reads]; // Error: invalid use of non-static data member 'Alarms::num_of_reads'
};
It’s simple but doesn't work. I tried flexible array members until I found that that feature is not supported in C++. Arduino compiles with C++. I tried many examples of the 'struct hack' but they all returned errors like this one:
struct Alarms {
// Configurable parameters
int number_of_reads = 24;
// State variables
int reads[];
} ar;
void setup_alarm() {
ar.reads = malloc(sizeof(int) * ar.number_of_reads); // Error: incompatible types in assignment of 'void*' to 'int [0]'
}
That looked promising but I suspect my ignorance is glowing brightly. Most struct hack examples call for declaring the struct and later initializing the struct variables. I’m hoping to not duplicate the struct.
I considered splitting the struct but that would be error prone and, well, another compile error:
struct Alarms2 {
int reads[ar.num_of_reads]; // Error: array bound is not an integer constant before ']' token
} ar2;
An alternative is to size the array and get the size later but it needs an explanation:
struct Alarms {
// Configurable parameters
int reads[ 24 ]; // Put number of reads to average between brackets
// State variables
int number_of_reads;
};
void setup_alarm() {
ar.number_of_reads = sizeof(ar.reads) / sizeof(ar.reads[0]); // this works
}
Is there a way to work the struct hack or some similar solution in Arduino to like achieve the first example?
The size of the struct must be known at compilation time. Const data types in structs can change per instance of the structure, that is why you are getting the invalid use of non-static data member 'Alarms::num_of_reads' when you try to initialize your array. The best way to solve this is to have an init_alarm and destroy_alarm functions. Like so ...
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_NUM_OF_READS (24)
struct alarm {
// Configurable parameters
const int number_of_reads;
// State variables
int *reads;
};
void init_alarm(struct alarm *alarm)
{
alarm->reads = (int *) malloc(alarm->number_of_reads * sizeof(int));
}
void destroy_alarm(struct alarm *alarm)
{
free(alarm->reads);
}
int main(int argc, char **argv)
{
// When we create our struct, set number_of_reads to default
struct alarm alarm = {.number_of_reads = DEFAULT_NUM_OF_READS, .reads = NULL};
init_alarm(&alarm);
alarm.reads[0] = 13;
alarm.reads[23] = 100;
printf("alarm.reads[0] = %d, alarm.reads[23] = %d\n", alarm.reads[0], alarm.reads[23]);
destroy_alarm(&alarm);
return 0;
}
Note: Inorder to use the designated initializer to initialize a structure you must compile with ANSI (C99) like so ...
gcc --std=c99 test.c -o test
I would have posted this in the spinroot Bug Reports, but the spinroot forum is not currently accepting new users... If someone out there in charge of that is reading this, please let me in :)
Something very odd is happening when I try to use the select statement. Promela does not allow select() to be called on the field of a struct, so I have to make a temporary variable like this:
typedef someStruct {
int someField;
}
someStruct struct;
inline SetSelect() {
int temp;
select(temp: -1 .. 1);
struct.someField = temp;
}
init{
SetSelect();
}
This runs fine. I tested it and struct.someField is correctly set to either -1, 0, or 1. However, when I try to just put the inlined code straight into the init() process, I get a syntax error. The code looks like this:
typedef someStruct {
int someField;
}
someStruct struct;
init{
int temp;
select(temp: -1 .. 1);
struct.someField = temp;
}
And the error message is:
spin: select_test.pml:9, Error: syntax error saw ''-' = 45'
BUG:
Indeed, it looks like a bug for version 6.4.6 of Spin.
(The bug is fixed in version 6.4.7)
Interestingly, You can make it go away by simply writing temp : instead of temp:.
I suggest you to contact Gerard Holzmann for filing a bug report. I would also mention the fact that select does not seem to work with a struct field, perhaps that can be fixed too (even if it might be by design).
SUGGESTION:
I am not entirely happy of creating an alias variable to get around the issue of the built-in select function with struct fields. Since the implementation of select is rather trivial, as can be found in the docs, I would introduce a novel inline function to replace the built-in select function:
typedef Struct
{
int field;
}
inline my_select (var, lower, upper)
{
var = lower;
do
:: var < upper -> var++;
:: break;
od;
}
init
{
Struct st;
my_select(st.field, -1, 1);
printf("%d\n", st.field);
}
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
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.
In this code snippet, the Init() function acts as a on-demand initializer that fills in all member variables of the structure. This is done to avoid calling default constructors all members of a large array on the stack:
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
This triggers a static analysis error in VS2012 with /analyze:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 17, 19, 20
I'm looking for a way to annotate Foo::Init() so that this warning doesn't occur. There are plenty of other ways to make the warning go away, including:
Adding an empty constructor
Moving Init() to the constructor and calling placement new in the loop
But I'd like to avoid changing the structure of the code.
I've tried the following annotation without success:
void _At_(this, _Out_) Init();
This syntax is accepted, but only changes the warning to be:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 18, 20, 21
warning C6001: Using uninitialized memory 'buffer[BYTE:0]'.: Lines: 18, 20, 21
Does anyone know how I can declare the intent of this Init() function to the static analysis engine?
Your question is somewhat elusive. You have shown SomeFunction taking int, but want annotation for method Init or constructor.
The warning shown is absolutely correct, assert won't hide the warning. You need to put if to check if n is greateer than 64 and reset n (or do something else, but not to loop when n>=64).
For annotation you need to use __in_bcount or similar alternative. An example:
bool SetBuffer(__in_bcount(8) const char* sBuffer);
Whichs says sBuffer is of 8 bytes (not elements).
You can read this this article for more information.
Too ugly to add an extra helper?
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void Initialize(__in_bcount(sizeof(Foo) * n) Foo* buffer, int n) {
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
Initialize(buffer, n);
// Use buffer[0] - buffer[n-1] somehow.
}
I found a work around by implementing a function to index the array. I flagged the return value as invalid so that this new function only escapes the uninitialized value check in the specific case where the return value is only used to initialize. I've only tested this in VS2017.
#define _Ret_invalid_ _SAL2_Source_(_Ret_invalid_, (), _Ret1_impl_(__notvalid_impl))
template <typename T>
_Ret_invalid_ T& UninitialzedIndex(T* pt, int index)
{
return pt[index];
}
Then, where the value is indexed, I call UninitialzedIndex instead of operator[]
void SomeFunction(int n) {
Foo buffer[64];
if (n <= 64)
return;
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
UninitialzedIndex(buffer, i).Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
Just add a default constructor (that calls Init()). What is wrong with that?
[Edit] The root problem is not how to lie to the static analyzer or your compiler. It is how to enforce that you don't leave foo in an uninitialized state. There is nothing wrong with adding a default constructor. I'd say the desire to NOT do it imposes risk.
Perhaps some client will use that poorly constructed foo class (Long after you wrote it and long after you are gone) and perhaps they will forget to call .Init() ?? What then? They will be left with data that is uninitialized.
If you are looking to enforce that rule, no amount of static analysis will help you there.
Take care of the foundation before you put on the roof.