MultiThreading and Uart write - multithreading

FIRST see below EDIT part.
I use beaglebone black, ker 3.8, and GCC compiler for a signal processing project.
I receive the raw data from three GPS modules through uart communication asynchronously. So, I used 3 threads which check 3 UARTs (BB-UART1, BB-UART2, BB-UART4) continuously to receive raw data, here called the "reading threads". after each data packet received from each module, I decode the received data packet and extract important data packet.
when, decoding is finished in the threads, I perform the signal processing in a separate thread, called "signal processing thread", using above 3-important decoded data packet.
as it's obvious, I should synchronize the reading threads with signal processing thread. I use pthread_cond_wait and pthread_cond_signal for that.
the code operates fine and synchronization and signal processing are performed efficiently. each data packet received in 0.1 second (10 times in a second).
In the signal processing thread, after signal processing, I send the signal processing result to the user through separate UART, BB-UART5.
when I add this part of the code, "THIS" line, after some time, which all parts or OK and the signal processing results are sent to user, the signal processing thread is frozen and locked in a mutex. In fact the mutex unlocking is not performed in previous step.
I spent many time, some weeks, to find the reason. when I remove the mutex and other tools for threads synchronization (to make the whole code simple to debug) an array of data in somewhere is overflowed and its data are changed to overflowed values. However when I don't add "THIS" line, overflow not occurred any time.
when I remove the "write" function (of BB-UART5) in signal processing thread all operations are OK.
the signal processing thread:
void *signal_processing_thread (void *arg){
int i, j;
char str[512];
printf("000000000000000000000000000000000000000000\r\n");
printf("0-signal_processing_thread is running!\r\n");
printf("000000000000000000000000000000000000000000\r\n");
while(1){
pthread_mutex_lock(&th1); // the code lock here after add "THIS" line
pthread_mutex_lock(&th2);
pthread_mutex_lock(&th3);
if ((!decode_completed[0])|(!decode_completed[1])|(!decode_completed[2])){
pthread_mutex_unlock(&th1);
pthread_mutex_unlock(&th2);
pthread_mutex_unlock(&th3);
continue;
}
// data packets are ready in reading threads
// signal processing start
// signal processing done
// send the results
sprintf (str,"some string\r\n\0",some variables);
printf (str);
for (i=0;i<256;i++)
if (str[i]==0)
break;
write (uart5_id, str, i); // "THIS" line
decode_completed [0] = 0;
decode_completed [1] = 0;
decode_completed [2] = 0;
pthread_cond_signal(&cv1);
pthread_mutex_unlock(&th1);
pthread_cond_signal(&cv2);
pthread_mutex_unlock(&th2);
pthread_cond_signal(&cv3);
pthread_mutex_unlock(&th3);
}
printf("signal processing thread is closed!\r\n");
}
the reading threads:
void *getdecodedata1_thread (void *arg){
int ret, count, count_decode=0;
char buffer[2024], buffer_decode[2024];
int i;
printf("1-getdecodedata_thread is running!\r\n");
count = 0;
pthread_mutex_lock(&th1);
while(1){
for (i=0;i<500;i++){
ret = read(uart1_id, buffer+count ,255);
if (ret<1)
continue;
// data received
count += ret;
if (count>1000) break;
}
if (count>0){ // packet received
for (i=0;i<count;i++)
buffer_decode1[count_decode3+i]=buffer[i];
count_decode1 += count;
if (count_decode1>15){
// decode
// ....
// decode done
}
count = 0;
}
if (decode is completed) {
decode_completed [0] = 1; // newdata
printf("WAIT_1\n");
pthread_cond_wait(&cv1,&th1);
pthread_mutex_unlock(&th1);
pthread_mutex_lock(&th1);
printf("RELEASE_1\n");
}
}
}
void *getdecodedata2_thread (void *arg){
int ret, count, count_decode=0;
char buffer[2024], buffer_decode[2024];
int i;
printf("2-getdecodedata_thread is running!\r\n");
count = 0;
pthread_mutex_lock(&th2);
while(1){
for (i=0;i<500;i++){
ret = read(uart2_id, buffer+count ,255);
if (ret<1)
continue;
// data received
count += ret;
if (count>1000) break;
}
if (count>0){ // packet received
for (i=0;i<count;i++)
buffer_decode3[count_decode2+i]=buffer[i];
count_decode2 += count;
if (count_decode2>15){
// decode
// ....
// decode done
}
count = 0;
}
if (decode is completed) {
decode_completed [1] = 1; // newdata
printf("WAIT_2\n");
pthread_cond_wait(&cv2,&th2);
pthread_mutex_unlock(&th2);
pthread_mutex_lock(&th2);
printf("RELEASE_2\n");
}
}
}
void *getdecodedata3_thread (void *arg){
int ret, count, count_decode=0;
char buffer[2024], buffer_decode[2024];
int i;
printf("3-getdecodedata_thread is running!\r\n");
count = 0;
pthread_mutex_lock(&th3);
while(1){
for (i=0;i<500;i++){
ret = read(uart4_id, buffer+count ,255);
if (ret<1)
continue;
// data received
count += ret;
if (count>1000) break;
}
if (count>0){ // packet received
for (i=0;i<count;i++)
buffer_decode3[count_decode3+i]=buffer[i];
count_decode3 += count;
if (count_decode3>15){
// decode
// ....
// decode done
}
count = 0;
}
if (decode is completed) {
decode_completed [2] = 1; // newdata
printf("WAIT_3\n");
pthread_cond_wait(&cv3,&th3);
pthread_mutex_unlock(&th3);
pthread_mutex_lock(&th3);
printf("RELEASE_3\n");
}
}
}
EDIT: I've found that the problem is in another place of the code. in some where I use "write" function to send some bytes to UART5 and in a separate thread I read simultaneously (non-blocking) UART5 to receive commands. I think a problem like "SegFault" is occurred and the above problem is seen. when I comment the "read" function of UART5, all things is correct and mutexes work finely. How can I use the UART5 to read and write simultaneously?

after about 2 months, I find that the problem is originated from an invalid event in an IC. I use a ttl to RS485 converter and its supply bus has sum noise and distortion which leads to send some invalid characters to serial input. In-fact when I send some characters using serial output, I think probably, serial input receive some invalid data. so it freezes the code in one of critical condition mechanisms. when I make the IC separate from the BBB, the problem is fixed.
I don't Know why? and How? How can a invalid data on serial input can make critical conditions lock? I use ttyO[] files to read and write the serial port.

Related

Program terminating while reference the front packet in queue

I have 2 threads to decode RTSP stream video, my code as below:
int key = 0;
std::queue<AVpacket> Packet_buf;
int thread1 (void)
{
AVPacket packet;
packet = read_packet();
Packet_buf.push(packet);
av_packet_unref(&packet);
key = 1;
}
int thread2 (void)
{
AVPacket *packet;
while(key==0) {} // wait to read the first packet
*packet = Packet_buf.front(); // program halt here
avcodec_send_packet(pCodecCtx,packet);
}
int main();
{
thread p1(thread1);
thread p2(thread2);
}
My program crash at line: *packet = Packet_buf.front();
Can you help me to find the problem, Thanks !
Your code have more the one issues, some of them:
1) std::queue<AVpacket> Packet_buf;
I think this would be:
std::queue<AVPacket> Packet_buf; notice AVpacket and AVPacket is whole different thing. (Yes, I'm guessing this just a typo).
2) while(key==0) {} This is not a good way to wait on a variable change. Especially if the variable (key) is not volatile. It may work and probably is working. But I suggest you use pthread signal and condition variables here instead. Also check next issue (3) which is closely related.
3) *packet = Packet_buf.front(); Caling std::queue.front() before checking whether the container is empty() or not is NOT good idea. If container (queue) is empty than front() method here will result in undefined behavior.
Hope that helps.

Linux multi-thread, pausing one thread while continue running the other threads within the same process

I cannot find a proper solution to my problem.
If i have more than one thread in one process. And I want to make only one thread to sleep while running the other threads within the same process, is there any predefined syntax for it or do i have to do my own implementation (sleep) ?
Ideally i want to send a indication from a thread to another thread when it is time for sleep.
Edited (2015-08-24)
I have two main threads, one for sending data over a network, the other receives the data from the network. Beside jitter, the receiving thread does validation and verification and some file management which in time could lead that it will drag behind. What i like to do is to add something like a micro sleep to the sender so that the receiver could catch up. sched_yield() will not help in this case because the HW has a multi core CPU with more than 40 cores.
From your description in the comments, it looks like you're trying to synchronize 2 threads so that one of them doesn't fall behind too far from the other.
If that's the case, you're going about this the wrong way. It is seldom a good idea to do synchronization by sleeping, because the scheduler may incur unpredictable and long delays that cause the other (slow) thread to remain stopped in the run queue without being scheduled. Even if it works most of the time, it's still a race condition, and it's an ugly hack.
Given your use case and constraints, I think you'd be better off using barriers (see pthread_barrier_init(3)). Pthread barriers allow you to create a rendezvous point in the code where threads can catch up.
You call pthread_barrier_init(3) as part of the initialization code, specifying the number of threads that will be synchronized using that barrier. In this case, it's 2.
Then, threads synchronize with others by calling pthread_barrier_wait(3). The call blocks until the number of threads specified in pthread_barrier_init(3) call pthread_barrier_wait(3), at which point every thread that was blocked in pthread_barrier_wait(3) becomes runnable and the cycle begins again. Essentially, barriers create a synchronization point where no one can move forward until everyone arrives. I think this is exactly what you're looking for.
Here's an example that simulates a fast sender thread and a slow receiver thread. They both synchronize with barriers to ensure that the sender does not do any work while the receiver is still processing other requests. The threads synchronize at the end of their work unit, but of course, you can choose where each thread calls pthread_barrier_wait(3), thereby controlling exactly when (and where) threads synchronize.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
pthread_barrier_t barrier;
void *sender_thr(void *arg) {
printf("Entered sender thread\n");
int i;
for (i = 0; i < 10; i++) {
/* Simulate some work (500 ms) */
if (usleep(500000) < 0) {
perror("usleep(3) error");
}
printf("Sender thread synchronizing.\n");
/* Wait for receiver to catch up */
int barrier_res = pthread_barrier_wait(&barrier);
if (barrier_res == PTHREAD_BARRIER_SERIAL_THREAD)
printf("Sender thread was last.\n");
else if (barrier_res == 0)
printf("Sender thread was first.\n");
else
fprintf(stderr, "pthread_barrier_wait(3) error on sender: %s\n", strerror(barrier_res));
}
return NULL;
}
void *receiver_thr(void *arg) {
printf("Entered receiver thread\n");
int i;
for (i = 0; i < 10; i++) {
/* Simulate a lot of work */
if (usleep(2000000) < 0) {
perror("usleep(3) error");
}
printf("Receiver thread synchronizing.\n");
/* Catch up with sender */
int barrier_res = pthread_barrier_wait(&barrier);
if (barrier_res == PTHREAD_BARRIER_SERIAL_THREAD)
printf("Receiver thread was last.\n");
else if (barrier_res == 0)
printf("Receiver thread was first.\n");
else
fprintf(stderr, "pthread_barrier_wait(3) error on receiver: %s\n", strerror(barrier_res));
}
return NULL;
}
int main(void) {
int barrier_res;
if ((barrier_res = pthread_barrier_init(&barrier, NULL, 2)) != 0) {
fprintf(stderr, "pthread_barrier_init(3) error: %s\n", strerror(barrier_res));
exit(EXIT_FAILURE);
}
pthread_t threads[2];
int thread_res;
if ((thread_res = pthread_create(&threads[0], NULL, sender_thr, NULL)) != 0) {
fprintf(stderr, "pthread_create(3) error on sender thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
if ((thread_res = pthread_create(&threads[1], NULL, receiver_thr, NULL)) != 0) {
fprintf(stderr, "pthread_create(3) error on receiver thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
/* Do some work... */
if ((thread_res = pthread_join(threads[0], NULL)) != 0) {
fprintf(stderr, "pthread_join(3) error on sender thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
if ((thread_res = pthread_join(threads[1], NULL)) != 0) {
fprintf(stderr, "pthread_join(3) error on receiver thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
if ((barrier_res = pthread_barrier_destroy(&barrier)) != 0) {
fprintf(stderr, "pthread_barrier_destroy(3) error: %s\n", strerror(barrier_res));
exit(EXIT_FAILURE);
}
return 0;
}
Note that, as specified in the manpage for pthread_barrier_wait(3), once the desired number of threads call pthread_barrier_wait(3), the barrier state is reset to the original state that was in use after the last call to pthread_barrier_init(3), which means that the barrier atomically unlocks and resets state, so it is always ready for the next synchronization point, which is wonderful.
Once you're done with the barrier, don't forget to free the associated resources with pthread_barrier_destroy(3).

Reading a device from kernel interrupt

I'm aiming to have a kernel module that reads a device (ADC) at every T seconds.
I already have a working module that calls a interrupt each T seconds and I also have another module that reads a user space file (the ADC, for instance), which I got from this example. Both work fine separately.
The problem is that when I try to open and read any file from my interrupt routine the module crashes
[ 80.636932] Kernel panic - not syncing: Fatal exception in interrupt
My code is something like this:
static irqreturn_t timer_irq_handler(int irq, void *dev_id)
{
uint16_t value;
// reset the timer interrupt status
omap_dm_timer_write_status(timer_ptr, OMAP_TIMER_INT_OVERFLOW);
omap_dm_timer_read_status(timer_ptr);
omap_dm_timer_set_load(timer_ptr, 1, 0xFFFFFFFF - (time * gt_rate);
value = read_channel();
return IRQ_HANDLED;
}
uint16_t read_channel()
{
// Create variables
struct file *f;
char buf[128];
mm_segment_t fs;
int i;
// Init the buffer with 0
for(i=0;i \< 128;i++)
buf[i] = 0;
f = filp_open(device, O_RDONLY, 0);
if(f == NULL)
printk(KERN_ALERT "filp_open error!!.\n");
else{
// Get current segment descriptor
fs = get_fs();
// Set segment descriptor associated to kernel space
set_fs(get_ds());
// Read the file
f->f_op->read(f, buf, 128, &f->f_pos);
// Restore segment descriptor
set_fs(fs);
// See what we read from file
printk(KERN_INFO "buf:%s\n",buf);
}
filp_close(f,NULL);
return 0;
}
static int __init mq7_driver_init(void)
{
int ret = 0;
struct clk *gt_fclk;
timer_ptr = omap_dm_timer_request();
if(timer_ptr == NULL){
printk("No more gp timers available, bailing out\n");
return -1;
}
// set the clock source to system clock
omap_dm_timer_set_source(timer_ptr, OMAP_TIMER_SRC_SYS_CLK);
// set prescalar to 1:1
omap_dm_timer_set_prescaler(timer_ptr, 0);
// figure out what IRQ our timer triggers
timer_irq = omap_dm_timer_get_irq(timer_ptr);
// install our IRQ handler for our timer
ret = request_irq(timer_irq, timer_irq_handler, IRQF_DISABLED | IRQF_TIMER , "mq7_driver", timer_irq_handler);
if(ret){
printk("mq7_driver: request_irq failed (on irq %d), bailing out\n", timer_irq);
return ret;
}
// get clock rate in Hz
gt_fclk = omap_dm_timer_get_fclk(timer_ptr);
gt_rate = clk_get_rate(gt_fclk);
// set preload, and autoreload
// we set it to the clock rate in order to get 1 overflow every 3 seconds
omap_dm_timer_set_load(timer_ptr, 1, 0xFFFFFFFF - (5 * gt_rate)); // dobro do tempo
// setup timer to trigger our IRQ on the overflow event
omap_dm_timer_set_int_enable(timer_ptr, OMAP_TIMER_INT_OVERFLOW);
// start the timer!
omap_dm_timer_start(timer_ptr);
// get acess to gpio
ret = gpio_request(gpio, "mq7_driver sck");
if (ret) {
printk(KERN_ALERT "gpio_request %d failed\n",gpio);
gpio_free(gpio);
return -1;
}
gpio_direction_output(gpio, 0);
// Print adc number into address string
sprintf(device,"/sys/class/hwmon/hwmon0/device/in%d_input",adc);
return 0;
}
What is wrong with reading a file from a interrupt routine?
P.S.: It's running on a Overo (ARM), the distro is Poky and kernel version is 3.5.7.
After reading the answer of #VivekS in this post I took a look at Linux Device Drivers, chapter 10, which states:
A handler can't transfer data to or from user space, because it
doesn't execute in the context of a process. Handlers also cannot do
anything that would sleep, such as calling wait_event, allocating
memory with anything other than GFP_ATOMIC, or locking a semaphore.
Finally, handlers cannot call schedule.

pthread Segmentation Faults

I am doing an assignment using pthreads and mutual exclusion. I have to create n print servers and m print clients, who each have 5 print jobs. We are to create the threads, pass the jobs through a queue of size 4 to the print servers which then print the job (ie busy work in this case). Here is the code for passing the jobs and servicing the jobs.
These are the client and server threads
void *PrintClient(void *arg){
int i;
char str[NUMJOBSPERCLIENT][100];
for(i=1;i<NUMJOBSPERCLIENT;i++){
pthread_mutex_lock(&mutex);
req.clientID = pthread_self();
req.fileSize = rand_int(FILEMIN,FILEMAX);
sprintf(str[i], "File_%d_%d",pthread_self(),i);
req.fileName = str[i];
append(req);
pthread_mutex_unlock(&mutex);
sleep(rand_int(1,3));
}//for
pthread_exit(NULL);
} // end PrintClient
void *PrintServer(void *arg){
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
while(count > 0){
take();
count = count -1;
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
} // end PrintServer
And this is code which adds or removes a job from the queue. I know the error is here and it had to do with the threads themselves but I can not find it for the life of me. So far the debugger has been almost no help (I am running on a university linux server which is showing no compile errors).
void append(PrintRequest item){
BoundBuffer[count] = req;
printf("I am client %s\n",req.fileName);
count++;
if(count == BUFSIZE){
printf("Buffer Size Reached\n");
pthread_cond_signal(&cond);
}
} // end append
PrintRequest take(){
printf("Printing %s\n", BoundBuffer[count].fileName);
usleep(BoundBuffer[count].fileSize/PRINTSPEED);
printf("Finished Printing %s\n", BoundBuffer[count].fileName);
} // end take
I guess the segmentation fault is signaled around printf("Printing %s\n", BoundBuffer[count].fileName);, right?
In your PrintClient, you store file name to local variable str[][] and copy the pointer to this local variable as one parameter of the request req.fileName = str[i];. Thus the address pointed by req.fileName is allocated on the stack of the client thread.
When the requests are processed in the server thread PrintServer, it is possible that the client thread which generated the request is no longer present. The result is that req.fileName points to an address which doesn't exists (the stack memory has already been de-allocated with the exiting of the client thread), then when you de-reference such address in printf("Printing %s\n", BoundBuffer[count].fileName);, segmentation fault is signaled.

epoll with timerfd

I want to use the it_interval of newValue to set the interval of the timeout.
But in my example, I can only print timeout once.
What happened? How can I set the interval?
This is my code:
int main()
{
int efd =epoll_create(256);
setnonblock(efd);
struct epoll_event ev,events[256];
int tfd;//timer fd
if((tfd= timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
cout<<"timerfd create error"<<endl;
struct itimerspec newValue;
struct itimerspec oldValue;
bzero(&newValue,sizeof(newValue));
bzero(&oldValue,sizeof(oldValue));
struct timespec ts;
ts.tv_sec = 5;
ts.tv_nsec = 0;
//both interval and value have been set
newValue.it_value = ts;
newValue.it_interval = ts;
if( timerfd_settime(tfd,0,&newValue,&oldValue) <0)
{
cout<<"settime error"<<strerror(errno)<<endl;
}
ev.data.fd = tfd;
ev.events = EPOLLIN | EPOLLET;
if( epoll_ctl(efd,EPOLL_CTL_ADD,tfd,&ev) < 0)
cout<<"epoll_ctl error"<<endl;
int num = 0;
while(1)
{
if((num=epoll_wait(efd,events,256,1000)) > 0)
{//justice
for(int i=0;i<num;i++)
{
if(events[i].data.fd == tfd)
{
cout<<"timeout"<<endl;
}
}
}
}
return 0;
}
It is because you are using EPOLLET and not read()ing the data produced into the tfd. The expiration of a timer "writes" 8 bytes of data that need to be read: you really need to read it. Add this when you print "timeout":
uint64_t value;
read(tfd, &value, 8);
In more details: EPOLLET asks for Edge Triggering, which means that epoll_wait() will say only once "data is ready for input" on the file descritor tfd until you read that data. In other words, as long as you didn't read that data, future calls to epoll_wait() will not return the same descriptor again. This behavior is useful with normal sockets, e.g. if you do epoll_wait() in the main thread, notice some data is ready, then fire up another thread to read it. The main thread goes immediately back to epoll_wait(). But we don't want it to wake up immediately again, even though the data from the file descriptor was probably not read yet.
Note that I guess your example without EPOLLET would be wrong too, differently: because you don't read(), the tfd is always readable after the initial delay, and so it would print "timeout" as fast as possible after the initial delay expires.

Resources