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-07-2009, 08:06 AM   #1
christyyim
Member
 
Registered: Oct 2008
Location: earth
Distribution: Ubuntu 'Gutsy Gibbon'
Posts: 32

Rep: Reputation: 15
How to use global variable in a multithreaded program?


My project is based on the program VLC media player, a multithreaded program. I wish to use a global variable as a counter in this program across various files and folders. How should I do this?

1 of the websites i refer was
http://circuitnegma.wordpress.com/20...-source-files/

but i cannot get it done in VLC media player. For example, in the VLC /modules/control/hotkeys.c, I don't know where the vlc_keys.h header file locates (which is 1 of the files i wish to include the global variable).

I had thought of writing another header file for the global variable, but i don't know how to include it in the makefile. So does anyone has idea on it?

Thanks a lot.
 
Old 01-07-2009, 09:43 AM   #2
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
I'm guessing here that you will encounter a major problem which has nothing to do with the question you ask. But I'll leave that major problem until the end of this post. I'll answer your actual question first.

My personal preference would be to avoid changing the makefile. Others may say differently, but they are made from sterner stuff than I am. :)

Find a header file (a .h file) in the project that's already included (directly or indirectly) by all the source files containing actual code (.c files) which you'll want to change to look at this variable. As shown in the URL you cite, declare the variable in the header file, and define the variable in the source code file.

That page does have one thing backwards, which might be confusing. It says:
Quote:
*** Note: The declaration source file should include (#include) the definition header file.
It really means:
Quote:
*** Note: The definition source file should include (#include) the declaration header file.
In other words, the .c file which defines the variable should include the .h file which declares the variable.

Then you can freely access that variable in not only the .c file which defines the variable, but also any other .c file which includes the .h file and is linked into the same executable as the .c file which defines the variable.

When you're done, it wouldn't hurt to force a complete recompilation. Most projects are defined so that you can do that thus:
Code:
make clean
make
or
Code:
make clean
make install
Now, as promised:

->->-> HERE IS YOUR MAJOR PROBLEM. <-<-<-

If this variable is to be accessed across threads, make sure you're protecting it with a mutex and a condition variable. These should also be global, just as the counter variable is.

Do not do any of this unless you are very familiar with pthreads programming. My guess is that if you're asking a question about header files and global variables, you're probably not familiar with pthreads programming.

pthreads programming is not rocket science, but it's far from trivial. The concepts are straightforward, but it's easy to miss some of the implications of those concepts and then find yourself immersed in seemingly infinite hours and hours of enjoyable debugging of a program which only misbehaves one percent of the time.

If my guess is right and you're not very familiar with pthreads programming, then run (do not walk) to your nearest bookseller and order a copy of Programming with POSIX Threads by David R. Butenhof. It's published by Addison Wesley.

My copy of the O'Reilly book on the same subject seems to have all the parts there, but it doesn't go out of its way to educate you on some aspects of the design philosophy of pthreads, and some of the implications of doing things wrong. That can cost you much open-ended debugging time. That, in my opinion, makes the O'Reilly book dangerous. Get the Addison Wesley one.

When you're familiar with pthreads programming, and you figure out how to introduce this counter variable without introducing deadlock (heh heh), you're all set!

Hope this helps.
 
Old 01-07-2009, 10:52 AM   #3
christyyim
Member
 
Registered: Oct 2008
Location: earth
Distribution: Ubuntu 'Gutsy Gibbon'
Posts: 32

Original Poster
Rep: Reputation: 15
Thanks wje_lq.

Quote:
Find a header file (a .h file) in the project that's already included (directly or indirectly) by all the source files containing actual code (.c files) which you'll want to change to look at this variable.
but i really cannot find out the vlc_keys.h header file in the /modules/control folder as used by hotkeys.c file in the VLC source tarball i downloaded from http://download.videolan.org/pub/vlc...-0.8.6f.tar.gz
Where would this header file locates?

Quote:
If this variable is to be accessed across threads, make sure you're protecting it with a mutex and a condition variable. These should also be global, just as the counter variable is.
that means i have to take care of those threads which will be using this counter variable to avoid the problem deadlock as you mentioned? How about other threads that do not use the counter variable? They won't be affected right?

Thanks.
 
Old 01-07-2009, 12:28 PM   #4
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
You use mutexes whenever you access data that is shared across threads. Threads that don't access that data don't need to use that mutex.
 
Old 01-07-2009, 01:26 PM   #5
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Where would this header file locates?
Unfortunately, I don't have the time to dig into that particular project. There are two ways you can approach this.
  1. Find the .c files in the project where you'll be interested in the counter.
  2. Find any .h file within the project which is included by all of these .c files, and modify that one.
The other approach, if the number of .c files involved with this counter is small, say two or three at the most, just take the line that you would have added to some .h file, and add it (identical in content) to each of these .c files. There's nothing that requires that the declaration be in a .h file; it's just that if you declare the variable in only one place, it's easier to maintain your code in the long run. But if you need to put the declaration in each of the .c files, just do it. But if I were you, I'd place a comment next to the declaration in each file listing all the .c files where this declaration exists, so if you change it in one place, you'll be able to find all the other places so you can change them too.

And the reason for protecting this variable with a mutex and a condition variable is not to protect against deadlock, but rather to provide data integrity. Deadlock will arise if you claim mutexes in the wrong order, so each of two threads is waiting on the other forever, or perhaps a similar but more complex situation.

Your question of the purpose of a mutex and a condition variable is a good one, but it illustrates the point that you really need to read almost from cover to cover the book I recommended, or there's a good chance you will quickly descend into troubles which are far beyond the scope of this or any other forum to help you out of.
 
Old 01-07-2009, 08:09 PM   #6
christyyim
Member
 
Registered: Oct 2008
Location: earth
Distribution: Ubuntu 'Gutsy Gibbon'
Posts: 32

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by wje_lq View Post
The other approach, if the number of .c files involved with this counter is small, say two or three at the most, just take the line that you would have added to some .h file, and add it (identical in content) to each of these .c files. There's nothing that requires that the declaration be in a .h file; it's just that if you declare the variable in only one place, it's easier to maintain your code in the long run. But if you need to put the declaration in each of the .c files, just do it. But if I were you, I'd place a comment next to the declaration in each file listing all the .c files where this declaration exists, so if you change it in one place, you'll be able to find all the other places so you can change them too.
Do you mean i do not need to declare the variable in the header file, but declare it in every .c files that it? What if the .c file is in another directory? How should i declare it in the file?

Thanks.
 
Old 01-07-2009, 08:49 PM   #7
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
To find 'vlc_keys.h', goto the root-directory of your project (or where the vlc source files are installed); then run this command:
Code:
find . -name vlc_keys.h
If you want to add a simple variable (an unsigned int for instance) to use as a counter, define it within an existing header file, or create your own header file. A good Makefile will not need to have a list of header files in it since header files that are needed by the project can be deduced by examining the .c files in the project (btw, this is known as building dependencies).

Anyhow, after you have defined your counter, go edit one or more .c files to increment (or decrement) your counter as needed, and also wherever necessary, display it.

For a simple data type such as an unsigned int, I don't think it is necessary to worry about protecting the write/read operations to it with a mutex since those operations will occur atomically using one CPU instruction.

For more complex data, where two or more steps are necessary to "massage" the data, then without a doubt, a mutex or semaphore would be needed to guard against concurrent access to the data.
 
Old 01-07-2009, 09:06 PM   #8
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
You need to be aware of the shape of the project you're building (or rebuilding). Keep in mind that global variables are used among various functions of the same program. It doesn't matter whether the .c files containing these functions are in the same directory or not. It only matters that the functions are linked together into the same executable program.

It still matters, though, that you be concerned about data integrity. dwhitney67 says:
Quote:
For a simple data type such as an unsigned int, I don't think it is necessary to worry about protecting the write/read operations to it with a mutex since those operations will occur atomically using one CPU instruction.
No, not so much. Consider the following simple source:
Code:
unsigned int a;

int main(void)
{
  a++;

  return 0;

} /* main() */
I compiled it with this command:
Code:
gcc -Wall 4.c -S
and got this output:
Code:
        .file   "4.c"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        movl    a, %eax
        incl    %eax
        movl    %eax, a
        movl    $0, %eax
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .comm   a,4,4
        .ident  "GCC: (GNU) 4.2.3"
        .section        .note.GNU-stack,"",@progbits
It takes those three instructions in red to increment a. If you have more than one thread which might be incrementing that count, you can have problems. Usually it will work, and one time out of, oh, a half zillion it won't.

If you're not worried about bulletproof, mission-critical accuracy, you can let it go and not worry about mutexes and condition variables. But once in a while your count will be off. Is this ok with you? If so, don't worry; be happy.
 
Old 01-07-2009, 11:30 PM   #9
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
Quote:
If you're not worried about bulletproof, mission-critical accuracy, you can let it go and not worry about mutexes and condition variables. But once in a while your count will be off. Is this ok with you? If so, don't worry; be happy.
That is pretty much it. If you don't use mutexes, then you will always have a race condition regarding access to that variable. It could be that it doesn't matter; if the variable is changed while being accessed, then a thread might loop one more time through a loop than it needs to, and this extra loop might cost nothing but a few CPU cycles. In this case, it really doesn't matter that much - and it is indeed a bit of extra work (only a bit) to employ a mutex.

I would normally consider it to be proper practice to always use a mutex, though, even in the case where it really doesn't matter. Why? Because it might not matter now, but after you make further modifications/upgrades to the program, suddenly that race condition becomes critical. If you employed the mutex from the beginning, you don't have to worry about it or even think about it. If you didn't use the mutex, then the change that makes it critical has introduced a bug that you'll have one hell of a time figuring out - unless, that is, you happen to remember or notice that you are accessing a variable without using a mutex.

Do it right the first time, then you can forget about it forever. Use the mutex, and you'll never find yourself surprised by that kind of bug.
 
Old 01-07-2009, 11:34 PM   #10
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Use the mutex
And the condition variable.

And Programming with POSIX Threads.
 
Old 01-08-2009, 12:44 AM   #11
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
I agree that you shouldn't even start programming until you've done some serious threading reading. If you don't understand what's going on (and why as above re mutex), you'll get a prog that
1. won't work
and
2. you can't debug

As above, its not rocket science, but it does require very careful attention to detail and a clear understanding of the principles.
Take it from someone who taught himself from the online perl docs ... not the easiest thing I've ever done
 
  


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
Multithreaded Program Ashok_mittal Linux - Newbie 2 01-04-2008 12:56 AM
Why does a multithreaded program gets hanged at recvfrom()? kranti Linux - Newbie 1 10-17-2005 04:40 AM
Probelm regarding multithreaded program? geethu Programming 2 08-10-2005 12:39 AM
Debugging Multithreaded Program villie Programming 2 08-17-2004 11:24 AM
Signal handling in Multithreaded program souvik Programming 4 08-23-2002 07:28 AM

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

All times are GMT -5. The time now is 08:15 AM.

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