How to know if a kernel code is atomic or not? - c

I am writing a kernel module where I implement some functions that are going to be used from another modules I have modified. When testing the system crashes. I get a "scheduling while atomic" error.
After debugging, I realized that the system crashes when a atomic_set() is called. It means that I am calling an atomic function from a non-atomic function? can't I use atomic_set() in this case? What should I use instead?
Also, as I said, I modified some original kernel files for calling my function. How could I know if where I am working is atomic code or not?
EDIT: Adding the actual code
In net/netfilter/ipvs/ip_vs_core.c line 451, I call my function:
my_callback(svc, skb);
Then, in another file I have:
int my_callback(struct ip_vs_service *svc, struct sk_buff *skb)
{
int swto;
printk(KERN_INFO "callback called \n");
swto = swtoing(svc);
return swto;
}
My swtoing() function is a bit long, but I had debugged a lot, and have figured out that the system does not crash if I comment a line within swtoing() with a atomic_set()...
Any help?
EDIT 2: More info
I realized that the kernel modules I am modifying are FULL of spin_locks and stuff like that... So I think (forgive me if I am wrong) that I must do something in the functions that I am creating, in order to keep the locking/atomic stuff... but I don't know what :(

You can use in_atomic macro but is has some restrictions. See the comment.

Related

MPLAB X, XC8, and C in general. Using variables across functions and source files

I am having a difficult time passing variables to functions--especially functions that are not in the same source file. I suspect these two problems are actually the same problem. I am sure this is somewhere on the internet, but I have done a lot of searching and I am now even more confused. Mostly I need someone to give me some direction on what I should be reading/searching for.
PROBLEM 1:
Say I have a source file named main.c. After the #includes and #defines, I declare a variable
int count;
I then declare a function
void increment () {
count++;
}
Within function main(); I call the function increment();, and then update PORTA to display it in LEDs. Both "count" and PORTA are assigned zero before main(); runs.
void main () {
increment();
PORTA = count;
}
The problem is that there appears to be two versions of "count". If this program was run, PORTA would never light an LED. However, if "PORTA = count;" were moved inside the function, it would increment properly. Furthermore, all hardware writes (Port, tris, etc) work fine inside the function, but variables I thought I declared globally do not. Thus, I assume the compiler is making a copy of "count" for the function call, and forgetting it when it returns.
I would normally just return a value from the function to get around this, but interrupt routines for the PIC cannot return a value, and I must use an interrupt.
What do I do? Surely I am missing a major concept!
PROBLEM 2: Example of a common issue
Say I am using the MLA device library and load the demo material for the HID_Mouse. Though it has ten million folders and source and header files that include each other, I am able to edit some of the subroutines and make it do my bidding. However, I need to declare a variable that is used both in main.c and modified by a function in app_device_mouse.c. How do I declare this thing so that it gets globally read/written, but I don't get declaration errors from the compiler?
../src/app_device_mouse.c:306: error: (192) undefined identifier "position_x"
i.e "You didn't declare 'int position_x' in app_device_mouse.c, even though you did in main.c
I'm not sure of the result of declaring it in both places, but something tells me that's a bad idea.
Thanks so much in advance for your time. I have learned a lot from this community!
-GB
For anyone who comes behind, the code in PROBLEM 1 was actually working code. My error instead was carelessly initializing my TRISC to 1 instead of 0xff; which means I was trying to run a button off an output. I should know better than that.
However, I was having this problem on other occasions by declaring my variables in main(); instead of outside the functions. This means I was trying to modify local variables inside a function that had not declared it - this was giving me nulls and garbage. Pedwards correctly identified that I was having trouble with global vs local variables; and "scope" was a really helpful keyword.
Declaring a variable as volatile is necessary for the variable to be modified by the ISR. After Oled's comment I was able to find this information on page 169 of the XC8 compiler manual.
What you're missing is called "scope". It's not specific to XC8, any C book will help you.
PIC interrupts won't take/return anything for a reason. Define a global in the same file as your ISR is defined and read/change that. If you're going to write to it from the ISR declare it 'volatile':
volatile int foo = 0x00;
If you need to access it from another file (beginners shall avoid this) declare it 'extern' in this file (or include):
extern int foo;

A bit rusty on c, how do I print useful information of this structure?

So I'm trying to debug a linux module someone else wrote and it's a while since I wrote anything in c/c++
I get an error here (this question is indirectly related to the error):
video_register_device(usbMightex->vdev, VFL_TYPE_GRABBER, video_nr)
so I wanted to try and find out what usbMightex->vdev is.
This it's structure:
http://www.linuxtv.org/downloads/legacy/video4linux/v4l2dwgNew.html
struct video_device
char name[32] :Canonical name for this device.
int type :Type of V4L2 device
(use type2 as well, look at videodev2.h for details on type2)
int minor :The device's minor number
struct file_operations *fops; :File operations used, which are displayed below
void (*release)(struct video_device *vfd); :Release function used by the driver to release
void *priv: :Can be used by the driver
I already have a pr_err statement that is used to print information but not sure how to use it. Not sure where it's defined. I think I'll be happy with a simple printf statement or smth similar so I can then pick up the output with dmesg
Thank you.
UPDATE
A commenter asked for some more information with regards to the error:
I have posted a different question about the problem generally here:
https://askubuntu.com/questions/565700/how-do-i-load-a-module-that-has-no-signature-in-ubuntu-12-04
This question is NOT about the error, it was merely about how to print some information that would potentially be useful in solving the error. Thank you to all that responded.
The most obvious answer is, use a debugger and put a breakpoint where you want to see the variables.
To print out in code then, assuming your linked page is correct (you should verify this by checking the header file, otherwise nonsense output may ensue):
printf("%31s\n", v->name);
printf("%d\n", v->type);
printf("%d\n", v->minor);
printf("%p\n", (void *)v->fops);
printf(PRIxMAX "\n", (uintmax_t)v->release);
printf("%p\n", priv);
where v is the pointer to the instance of the structure.
If it is compiled as kernel module (*.ko), you could probably insert and remove it multiple times without reboot
lsmod, modprobe, insmod etc
And you might find useful printk() functions, they output to syslog which goes into dmesg IIRC

Reentrancy or not with this netbsd code

I am studying on "reading code" by reading pieces of NetBSD source code.
(for whoever is interested, it's < Code Reading: The Open Source Perspective > I'm reading)
And I found this function:
/* convert IP address to a string, but not into a single buffer
*/
char *
naddr_ntoa(naddr a)
{
#define NUM_BUFS 4
static int bufno;
static struct {
char str[16]; /* xxx.xxx.xxx.xxx\0 */
} bufs[NUM_BUFS];
char *s;
struct in_addr addr;
addr.s_addr = a;
strlcpy(bufs[bufno].str, inet_ntoa(addr), sizeof(bufs[bufno].str));
s = bufs[bufno].str;
bufno = (bufno+1) % NUM_BUFS;
return s;
#undef NUM_BUFS
}
It introduces 4 different temporary buffers to wrap inet_ntoa function since inet_ntoa is not re-entrant.
But seems to me this naddr_ntoa function is also not re-entrant:
the static bufno variable can be manipulated by other so the temporary buffers do not seem work as expected here.
So is it a potential bug?
Yes, this is a potential bug. If you want a similar function that most likely reentrant you could use e.g. inet_ntop (which incidentally handles IPv6 as well).
That code comes from src/sbin/routed/trace.c and it is not a general library routine, but just a custom hack used only in the routed program. The addrname() function in the same file makes use of the same trick, for the same reason. It's not even NetBSD code per se, but rather it comes from SGI originally, and is maintained by Vernon Schryver (see The Routed Page).
It's just a quick hack to allow use of multiple calls within the same expression, such as where the results are being used in one printf() call: E.g.:
printf("addr1->%s, addr2->%s, addr3->%s, addr4->%s\n",
naddr_ntoa(addr1), naddr_ntoa(addr2), naddr_ntoa(addr3), naddr_ntoa(addr4));
There are several examples of similar uses in the routed source files (if.c, input.c, rdisc.c).
There is no bug in this code. The routed program is not multi-threaded. Reentrancy is not being addressed at all in this hack. This trick has been done by design for a very specific purpose that has nothing to do with reentrancy. The Code Reading author(s) is wrong to associate this trick with reentrancy.
It's simply a way to hide the saving of multiple results in an array of static variables instead of having to individually copy those results from one static variable into separate storage in the calling function when multiple results are required for a single expression.
Remember that static variables have all the properties of global variables except for the limited scope of their identifier. It is of course true that unprotected use of global (or static) variables inside a function make that function non-reentrant, but that's not the only problem global variables cause. Use of a fully-reentrant function would not be appropriate in routed because it would actually make the code more complex than necessary, whereas this hack keeps the calling code clean and simple. It would though have been better for the hack to be properly documented such that future maintainers would more easily spot when NUM_BUFS has to be adjusted.

Segmentation fault while accessing a function-static structure via returned pointer

I have the following structure:
struct sys_config_s
{
char server_addr[256];
char listen_port[100];
char server_port[100];
char logfile[PATH_MAX];
char pidfile[PATH_MAX];
char libfile[PATH_MAX];
int debug_flag;
unsigned long connect_delay;
};
typedef struct sys_config_s sys_config_t;
I also have a function defined in a static library (let's call it A.lib):
sys_config_t* sys_get_config(void)
{
static sys_config_t config;
return &config;
}
I then have a program (let's call it B) and a dynamic library (let's call it C). Both B and C link with A.lib. At runtime B opens C via dlopen() and then gets an address to C's function func() via a call to dlsym().
void func(void)
{
sys_get_config()->connect_delay = 1000;
}
The above code is the body of C's func() function and it produces a segmentation fault when reached. The segfault only occurs while running outside of gdb.
Why does that happen?
EDIT: Making sys_config_t config a global variable doesn't help.
The solution is trivial. Somehow, by a header mismatch, the PATH_MAX constant was defined differently in B's and C's compilation units. I need to be more careful in the future. (facepalms)
There is no difference between the variable being a static-local, or a static-global variable. A static variable is STATIC, that means, it is not, on function-call demand, allocated on the stack within the current function frame, but rather it is allocated in one of the preexisting segments of the memory defined in the executable's binary headers.
That's what I'm 100% sure. The question, where in what segment they exactly placed, and whether they are properly shared - is an another problem. I've seen similar problems with sharing global/static variables between modules, but usually, the core of the problem was very specific to the exact setup..
Please take into consideration, that the code sample is small, and I worked on that platforms long time ago. What I've written above might got mis-worded or even be plainly wrong at some points!
I think, that the important thing is that you are getting that segfault in C when touching that line. Setting an integer field to a constant could not have failed, never, provided that target address is valid and not write-protected. That leaves two options:
- either your function sys_get_config() has crashed
- or it has returned an invalid pointer.
Since you say that the segfault is raised here, not in sys_get_config, the only thing left is the latter point: broken pointer.
Add to the sys_get_config some trivial printf that will dump the address-to-be-returned, then do the same in the calling function "func". Check whether it not-null, and also check if within sys_get_config it is the same as after being returned, just to be sure that calling conventions are proper, etc. A good idea for making a double/triple check is to also add inside the module "A" a copy of the function sys_get_config (with different name of course), and to check whether the addresses returned from sys_get_config and it's copy are the same. If they are not - something went very wrong during the linking
There is also a very very small chance that the module loading has been deferred, and you are trying to reference a memory of a module that was not fully initialized yet.. I worked on linux very long time ago, but I remember that dlopen has various loading options. But you wrote that you got the address by dlsym, so I suppose the module has loaded since you've got the symbol's final address..

Access command line arguments without using char **argv in main

Is there any way to access the command line arguments, without using the argument to main? I need to access it in another function, and I would prefer not passing it in.
I need a solution that only necessarily works on Mac OS and Linux with GCC.
I don't know how to do it on MacOS, but I suspect the trick I will describe here can be ported to MacOS with a bit of cross-reading.
On linux you can use the so called ".init_array" section of the ELF binary, to register a function which gets called during program initilization (before main() is called). This function has the same signature as the normal main() function, execept it returns "void".
Thus, you can use this function to remember or process argc, argv[] and evp[].
Here is some code you can use:
static void my_cool_main(int argc, char* argv[], char* envp[])
{
// your code goes here
}
__attribute__((section(".init_array"))) void (* p_my_cool_main)(int,char*[],char*[]) = &my_cool_main;
PS: This code can also be put in a library, so it should fit your case.
It even works, when your prgram is run with valgrind - valgrind does not fork a new process, and this results in /proc/self/cmdline showing the original valgrind command-line.
PPS: Keep in mind that during this very early program execution many subsystem are not yet fully initialized - I tried libc I/O routines, they seem to work, but don't rely on it - even gloval variables might not yet be constructed, etc...
In Linux, you can open /proc/self/cmdline (assuming that /proc is present) and parse manually (this is only required if you need argc/argv before main() - e.g. in a global constructor - as otherwise it's better to pass them via global vars).
More solutions are available here: http://blog.linuxgamepublishing.com/2009/10/12/argv-and-argc-and-just-how-to-get-them/
Yeah, it's gross and unportable, but if you are solving practical problems you may not care.
You can copy them into global variables if you want.
I do not think you should do it as the C runtime will prepare the arguments and pass it into the main via int argc, char **argv, do not attempt to manipulate the behaviour by hacking it up as it would largely be unportable or possibly undefined behaviour!! Stick to the rules and you will have portability...no other way of doing it other than breaking it...
You can. Most platforms provide global variables __argc and __argv. But again, I support zneak's comment.
P.S. Use boost::program_options to parse them. Please do not do it any other way in C++.
Is there some reason why passing a pointer to space that is already consumed is so bad? You won't be getting any real savings out of eliminating the argument to the function in question and you could set off an interesting display of fireworks. Skirting around main()'s call stack with creative hackery usually ends up in undefined behavior, or reliance on compiler specific behavior. Both are bad for functionality and portability respectively.
Keep in mind the arguments in question are pointers to arguments, they are going to consume space no matter what you do. The convenience of an index of them is as cheap as sizeof(int), I don't see any reason not to use it.
It sounds like you are optimizing rather aggressively and prematurely, or you are stuck with having to add features into code that you really don't want to mess with. In either case, doing things conventionally will save both time and trouble.

Resources