LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-23-2008, 05:29 PM   #1
R00ts
Member
 
Registered: Mar 2004
Location: Austin TX, USA
Distribution: Ubuntu 11.10, Fedora 16
Posts: 547

Rep: Reputation: 30
Synchronization with pthreads example


I'm working on making a code base to be multi-thread safe and diving into pthreads. I have C code that looks something like the block below. Basically all it is doing is waiting for the state of a few variables to change (changed by an external thread/routine) and waiting with a possible time out condition.

Code:
while ((err_flag) || (G_signoopflag) || (G_sigechoflag) || (G_sigvalue != SIG_DELAY)) 
{
   errorcheck(my_timeout, "Waiting for SIG_DELAY signal");
}
Everything prefixed with "G_" is a global variable (yes, I know they are evil and I'm fixing that). The way this particular program is multi-threaded is that it can receive a signal from an external device, and a signal generates an interrupt in which a user-defined ISR is invoked (this ISR also happens to modify all of those globals in that while loop above). So to protect these signals and ensure correct operation of the program, I did the following:

1) Create a pthread_mutex_t object
2) Protect the ISR by acquiring the mutex in the beginning of the function and releasing it just before the function returns
3) Modify the loop above as follows:


Code:
int wait_condition = 1;
while ((err_flag) || (wait_condition)) 
{
   pthread_mutex_lock(mutex); // blocks until mutex is locked by this thread
   if ((G_signoopflag) || (G_sigechoflag) || (G_sigvalue != SIG_DELAY))
     wait_condition = 0;
   pthread_mutex_unlock(mutex);

   errorcheck(my_timeout, "Waiting for SIG_DELAY signal");
}
(Ignore the fact that I didn't check return values to the pthread calls here please.)

So what I do is I make sure I have acquired the mutex before I read the value of any of those globals, and then subsequently release the lock afterwards. The reason I release it in the loop instead of holding on to it is because I expect that ISR to execute sometime while I'm polling on this condition, but the ISR also needs the mutex to execute so I have to release it to prevent deadlock.


This was more of a quick hack than an elegant fix, but I thought it did the trick. Then my co-worker comes over and says that "ideally", what I want to do is have some number of semaphores or something on that entire condition and eliminate that polling while loop completely. He wants something like this (pseudo-code):

Code:
acquire_something((G_signoopflag) || (G_sigechoflag) || (G_sigvalue != SIG_DELAY));
release_something(...);
// continue execution of program

I honestly don't know how the heck you can even do something like that. Sure, I could make a semaphore/mutex for each of those global variables and require my code to acquire all of them before it is allowed to release them and continue, but there are a number of problems I see with this approach.

1) I can no longer check for my time-out condition. If I never acquire the mutex/semaphore because the ISR didn't set those globals to the value I expected, my program will continue to run until I kill it.

2) For this one case it is fine, but there are possibly hundreds of combinations of "conditions" like this in the code I'm working with. If I have to create a different structure for each of those combinations, well that's just not an acceptable solution to me.


I was thinking that maybe I could use condition variables like so, but I'm not entirely sure of how they work right now in the pthread library:

Code:
pthread_mutex_lock(&mutex);
  while ((err_flag) ||(G_signoopflag) || (G_sigechoflag) || (G_sigvalue != SIG_DELAY)) {
    pthread_cond_wait(&condition_var, &mutex);
  }
pthread_mutex_unlock(&mutex);

Or another idea I had was to yield the main thread/process in my version of the code where the while loop polls and the mutex is acquired and released within the loop (I would yield if I detect that I'm not yet ready to leave the loop). That would give other threads/processes more CPU time while I wait for that signal to cause the ISR to execute.

What I am hoping to confirm through this discussion is:

1) Is my co-worker's proposed "ideal" solution practical?

2) Can I use condition variables as I did in the example above? Or can a condition variable only be dependent on *one* variable and not multiple?

3) Is my idea of yielding the main thread through sequences of that polling while loop an acceptable solution?

4) For the particular example that I used in this post, what would you personally consider an optimal solution? (I know it depends on the context of the program, etc. But just imagine its going to the a single user-space program and the only one that really needs to be executing on the system).



Thanks in advance for any insights you can provide me. I've studied this material when I was in school, but this is my first "real-world" experience with this type of programming.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
email synchronization (not file synchronization) Moebius Linux - Software 6 10-05-2004 05:31 AM
pthreads socket9001 Programming 2 12-29-2003 12:23 AM
pthreads Keith Hampton Linux - Software 1 10-23-2003 01:46 PM
pthreads h/w Programming 5 10-09-2003 11:11 AM
pthreads fr0ggeh Linux - Software 9 07-18-2003 10:43 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:54 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration