Linux kernel module blocking entire Linux - linux

I wrote my the first simple Linux module for Led flashing. If I use for pause between Led ON and Led Off the command ssleep(1) then everything is okay but if I use udelay(40) then entire Linux and applications such as SSH, Webserver etc are frozen. Could you help me why it happens and how fix it ?
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
MODULE_LICENSE("GPL");
static int led_on_init(void)
{
gpio_direction_output(AT91_PIN_PA24, 0);
int i = 1;
while (i == 1)
{
gpio_set_value(AT91_PIN_PA24, 1);
/*udelay(40);*/
ssleep(1);
gpio_set_value(AT91_PIN_PA24, 0);
ssleep(1);
/*udelay(40);*/
}
}
static void led_on_exit(void)
{
gpio_set_value(AT91_PIN_PA24, 0);
}
module_init(led_on_init);
module_exit(led_on_exit);

udelay is a busy-waiting function while sleep will schedule the current task out(to run other tasks) and go back when the time is up.
So if your kernel is not configured as preemptible one, the cpu which is running udelay won't have chance to be scheduled. If your machine only has 1 cpu, the entire machine will be blocked.
In your circumstance, it's recommended to use sleep instead of udelay.

Related

C++ data sharing between threads c++

Originally coming from Java, I'm having problem with data sharing between 2 threads in C++11. I have thoroughly read through the multithreading posts here without help and i would simply like to know why my approach is not OK C++ syntax for multithreading.
My application in short:
I have one thread reading a hardware sensor and dumping that data to some shared data monitor
I want another thread listening to data changes of that very monitor and draw some graphical stuff based on the new data (yes, I'm using conditional varible in my monitor)
Below is my Main class with the main method:
#include <cstdlib>
#include <iostream>
#include <thread>
#include <sweep/sweep.hpp>
#include <pcl/ModelCoefficients.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/features/normal_3d.h>
#include "include/LiDAR.h"
#include "include/Visualizer.h"
void run_LiDAR(LiDAR* lidar){
lidar->run();
}
void visualize(Visualizer* visualizer){
visualizer->run();
}
int main(int argc, char* argv[]) try {
Monitor mon; //The monitor holding shared data
LiDAR sensor(&mon); //Sensor object dumping data to the monitor
Visualizer vis(&mon); //Visualizer listening to data changes and updates the visuals accordingly
std::thread sweep_thread(run_LiDAR, &sensor); //Starting the LiDAR thread
std::cout << "Started Sweep thread" << std::endl;
std::thread visualizer_thread(visualize, vis);
std::cout << "Started Visualizer thread" << std::endl;
while(1){
//Do some calculations on the data in Monitor mon
mon.cluster();
}
}
The sensor thread dumping the data works good and so does the main thread running the clustering algorithms. However I get the following error message:
In file included from MY_DIRECTORY/Main.cpp:3: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/thread:336:5: error: attempt to use a deleted function
__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
If I comment the line:
std::thread visualizer_thread(visualize, vis);
My program builds and works...
What am I not getting?
Kind regards,
What is happening is that Visualizer doesn't have a move constructor.
std::thread visualizer_thread(visualize, vis);
visualize() expects a pointer.
As an aside, you should make you have a mechanism to end your threads in an orderly manner, since the data (sensor, vis) will destroy itself when main() exits, leaving the threads reading/writing to unallocated data on the stack!
Using dynamic allocation using std::unique_ptr or std::shared_ptr (which are moveable) can eliminate the issue.

linux RT scheduling

Our product is running linux 2.6.32, and we have some user space processes which run periodically - 'keep alive - like' processes. We don't place hard requirements on these processes - they just need to run once in several seconds and refresh some watchdog.
We gave these processes a scheduling class of RR or FIFO with max priority, and yet, we see many false positives - it seems like they don't get the CPU for several seconds.
I find it very odd because I know that Linux, while not being a RT OS, can still yield very good performance (I see people talking about orders of several msec) - and I can't even make that the process run once in 5 sec.
The logic of Linux RT scheduler seems very straight forward and simple, so I suspected that these processes get blocked by something else - I/O contention, interrupts or kernel threads taking too long - but now I'm not so sure:
I wrote a really basic program to simulate such a process - it wakes up every 1 second and measures the time spent since the last time it finished running. The time measurement doesn't include blocking on any I/O as far as I understand, so the results printed by this process reflect the behavior of the scheduler:
#include <sched.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/param.h>
#include <time.h>
#define MICROSECONDSINASEC 1000000
#define MILLISECONDSINASEC 1000
int main()
{
struct sched_param schedParam;
struct timeval now, start;
int spent_time = 0;
time_t current_time;
schedParam.sched_priority = sched_get_priority_max(SCHED_RR);
int retVal = sched_setscheduler(0, SCHED_RR, &schedParam);
if (retVal != 0)
{
printf("failed setting RT sched");
return 0;
}
gettimeofday(&start, 0);
start.tv_sec -= 1;
start.tv_usec += MICROSECONDSINASEC;
while(1)
{
sleep(1);
gettimeofday(&now, 0);
now.tv_sec -= 1;
now.tv_usec += MICROSECONDSINASEC;
spent_time = MILLISECONDSINASEC * (now.tv_sec - start.tv_sec) + ((now.tv_usec - start.tv_usec) / MILLISECONDSINASEC);
FILE *fl = fopen("output_log.txt", "aw");
if (spent_time > 1100)
{
time(&current_time);
fprintf(fl,"\n (%s) - had a gap of %d [msec] instead of 1000\n", ctime(&current_time), spent_time);
}
fclose(fl);
gettimeofday(&start, 0);
}
return 0;
}
I ran this process overnight on several machines - including ones that don't run our product (just plain Linux) and I still saw gaps of several seconds - even though I made sure the process DID get the priority - and I can't figure out why - technically this process should preeampt any other running process, so how can it wait so long to run?
A few notes:
I ran these processes mostly on virtual machines - so maybe there can be an intervention from the hypervisor. But in the past I've seen such behavior on physical machines as well.
Making the process RT did improve the results drastically, but not totally prevented the problem.
There are no other RT processes running on the machine except for the Linux migration and watchdog process (which I don't believe can cause starvation to my processes).
What can I do? I feel like I'm missing something very basic here.
thanks!

threads and locks

I do not not know anything about multithreading programming so wanted to post a general question here. How can I do the following:
main()
run MyMethod every 30 seconds
MyMethod()
1. get data
2. do calculations
3. save result into file
How can I make sure that I finish saving results (MyMethod step 3) before main start running MyMethod again ? Basically I have to lock that thread somehow until MyMethod is done. Feel free to use any language as example I'm more interested in the concept how such things are done in reality.
Thanks
You don't need synchronization. You only need to make sure that the thread work is completed, since saving happens at the end.
#include <thread>
#include <unistd.h>
int MyMethod(){
// some code
}
int run(){
std::thread thrd(MyMethod);
sleep(30);
thrd.join();
}
int main(){
while(true)
run();
}

Saving gmon.out before killing a process

I would like to use gprof to profile a daemon. My daemon uses a 3rd party library, with which it registers some callbacks, then calls a main function, that never returns. I need to call kill (either SIGTERM or SIGKILL) to terminate the daemon. Unfortunately, gprof's manual page says the following:
The profiled program must call "exit"(2) or return normally for the
profiling information to be saved in the gmon.out file.
Is there is way to save profiling information for processes which are killed with SIGTERM or SIGKILL ?
First, I would like to thank #wallyk for giving me good initial pointers. I solved my issue as follows. Apparently, libc's gprof exit handler is called _mcleanup. So, I registered a signal handler for SIGUSR1 (unused by the 3rd party library) and called _mcleanup and _exit. Works perfectly! The code looks as follows:
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
void sigUsr1Handler(int sig)
{
fprintf(stderr, "Exiting on SIGUSR1\n");
void (*_mcleanup)(void);
_mcleanup = (void (*)(void))dlsym(RTLD_DEFAULT, "_mcleanup");
if (_mcleanup == NULL)
fprintf(stderr, "Unable to find gprof exit hook\n");
else _mcleanup();
_exit(0);
}
int main(int argc, char* argv[])
{
signal(SIGUSR1, sigUsr1Handler);
neverReturningLibraryFunction();
}
You could add a signal handler for a signal the third party library doesn't catch or ignore. Probably SIGUSR1 is good enough, but will either have to experiment or read the library's documentation—if it is thorough enough.
Your signal handler can simply call exit().

What happens in Eclipse CDT on Linux if you press the Terminate button?

I guess some signals will be sent to the process. Some or one? If more than one in which order do they occure?
And what happens if the Terminate button is pressed and if the process has forked?
And what happens if the process has started other processes by system(...)?
I can't be sure without checking, but I would be surprised if the signal sent was anything other than SIGTERM (or possibly SIGKILL, but that would be a bit unfriendly of CDT).
As for sub-processes, depends what they are actually doing. If they are communicating with their parent processes over a pipe (in any way whatsoever, including reading their stdout), they'll likely find that those file descriptors close or enter the exception state; if they try to use the fds anyway they'll be sent a SIGPIPE. There may also be a SIGHUP in there.
If a sub-process was really completely disjoint (close all open FDs, no SIGTERM handler in the parent which might tell it to exit) then it could theoretically keep running. This is how daemon processes are spawned.
I checked SIGTERM, SIGHUP, SIGPIPE with terminate button. Doesn't work...
I guess it is SIGKILL and this makes me very sad! Also, I didn't find a good solution to run program from external(or built-in plugin) console.
It seems to be SIGKILL. SIGSTOP is used by GDB to stop/resume. From signal man page:
The signals SIGKILL and SIGSTOP cannot be caught or ignored.
I tried to debug following program with eclipse. Pressing terminate in Run session or pause in Debug session does not print anything. Thus it must be either SIGKILL or SIGSTOP.
#include <signal.h>
#include <string.h>
#include <unistd.h>
void handler(int sig) {
printf("\nsig:%2d %s\n", sig, strsignal(sig));
}
int main(int argc, char **argv) {
int signum;
int delay;
if (argc < 2) {
printf("usage: continue <sleep>\n");
return 1;
}
delay = atoi(argv[1]);
for (signum = 1; signum < 64; signum++) {
signal(signum, handler);
}
printf("sleeping %d s\n", delay);
for(;;) {
sleep(delay);
}
return 0;
}

Resources