Thread: pthread and shared variables

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    10

    pthread and shared variables

    Hi all,

    I am trying to share a character array as shared data container between a pthread and the main program. Not really that experienced in C programming so not able to find out what is wrong with what I have done. Anyone able to have a quick look?

    Bacically what I do is the following:

    1) define the variable at the start of my main code:

    Code:
    char *DATA;
    int READY=0;
    2) start the thread with:

    Code:
    pthread_create(&threads[0], NULL, run_thread, 0);
    3) which calls:

    Code:
    void *run_thread(void *threadid)
    {
            runThread(&READY,DATA);
    }
    4) and then the thread sets the DATA as below:

    Code:
    void runThread(int *ready,char *data)
    {
       ...
       data=(char *)malloc(length+1);
       strncpy(data,buffer,length);
       *ready=1;
       ...
    {
    5) Finally I wait for the thread in the main code and get the value as below:

    Code:
    while(READY==0){
          sleep(1);
    }
    printf("VALUE:%s",DATA);
    Now what happens with the above is that the value for DATA is NULL everytime. I have checked that is gets set in the thread, but somehow it does not carry over to the main code. A bit like the variable in the thread is a copy of the original variable.

    Probably some C principle that I don't quite understand, so if someone would take a minute and point out that would be great

    Thanks for your help in advance,

    Olli

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    10
    Figured it out. Learn a new thing about C programming again. I don't actually need to pass the variables in as function parameters since everything in visible to the threads anyway

    So I can just set the value of DATA in my thread directly.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by ojaro View Post
    Figured it out. Learn a new thing about C programming again. I don't actually need to pass the variables in as function parameters since everything in visible to the threads anyway

    So I can just set the value of DATA in my thread directly.
    Yes, but the actual problem was you were attempting to change the value of a variable by altering a function parameter. This mistake is made all the time by beginners regardless of threading or anything else
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> 5) Finally I wait for the thread in the main code and get the value as below:
    That code is incorrect. When two or more threads access the same memory location, and at least one of those threads is writing - then you must use pthread synchronization primitives to access that data.

    In this case you'll want to use to a condition variable to signal "data ready", and a mutex to protect access to "DATA".

    gg

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Codeplug View Post
    >> 5) Finally I wait for the thread in the main code and get the value as below:
    That code is incorrect. When two or more threads access the same memory location, and at least one of those threads is writing - then you must use pthread synchronization primitives to access that data.

    In this case you'll want to use to a condition variable to signal "data ready", and a mutex to protect access to "DATA".

    gg
    Wouldn't it be sufficient to declare the variable as sig_atomic_t? If it can be safely accessed from asychronous context then surely it can be accessed in a multithread context, though I'm not sure what the standards say about it.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Posix-2008, 4.11 is here: http://www.opengroup.org/onlinepubs/...html#tag_04_11

    The FCD ballot draft for "C++0x" (N3092) says:
    1.10 - 3
    Two expression evaluations conflict if one of them modifies a memory location and the other one accesses or modifies the same memory location.
    ...
    1.10 - 14
    The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other....
    To have "happens before", you have to use synchronization primitives provided by C++0x, like atomics.

    >> Wouldn't it be sufficient to declare the variable as sig_atomic_t?
    Writing to a volatile sig_atomic_t is the only global variable access allowed by Posix in a signal handler. For C++0x we have:
    When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects which are neither
    — of type volatile std::sig_atomic_t nor
    — lock-free atomic objects (29.4)
    are unspecified, and the value of any object not in either of these two categories that is modified by the handler becomes undefined.
    Only good for signal handlers.

    [edit]uh-oh, C++ in the C forum...[/edit]

    gg

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Codeplug View Post
    Only good for signal handlers.
    I realize the standard does not say it, but I'm going to make a heuristic argument that it's probably safe for multithread as well. If memory access to a sig_atomic_t type is guaranteed atomic in the context of a signal handler, then it is atomic in any context. A signal handler could interrupt execution at literally any point, including in the middle of a multi-word memory access. Therefore, if sig_atomic_t is safe in that context, then sig_atomic_t must either A) be of a type which is accessed atomically by the hardware, or B) be a type which is implicitly protected by compiler-generated locking primitives so that from the program's perspective, access is always atomic.

    1. If sig_atomic_t is a type which is hardware atomic, then all accesses are safe regardless of context because the hardware guarantees it.

    2. If sig_atomic_t is a type which is implicitly protected by the compiler, then the compiler should generate the same protection regardless of context. sig_atomic_t must be safely accessible from main program code and asynchronous handler code. Main program code is indistinguishable from handler code -- the compiler has no way to know whether a given piece of code is executed with signals masked, or in fact whether it is a signal handler at all. Therefore it must produce the protection in all contexts, including multi-thread contexts (again, the compiler has no way of knowing if a piece of code is multi-threaded or not).
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Under both standards, it's undefined behavior to access the same memory location by two or more threads where at least one is writing.

    So it's not really an "argument", but more an exploration of "what behavior will I get from my compiler and hardware?".

    That aside, your logic is faulty in that signal handling and multi-threading are unrelated concepts.

    Signals are dispatched by the OS directly to the task/thread that is to handle them. There is only a single thread of execution - which is interrupted long enough to execute the signal handler. There are no memory accesses by other threads to the volatile sig_atomic_t that the handler would write to. So conforming implementations just have to ensure that loads and stores of volatile sig_atomic_t are atomic with respect to signals (on a single thread).

    Multiple threads accessing the same memory location introduces new issues of memory visibility and ordering. These issues can only be solved using the synchronization primitives of your threading library.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. pthread heap separated like stack??
    By mynickmynick in forum C++ Programming
    Replies: 1
    Last Post: 08-25-2008, 11:11 AM
  2. pthread safe library functions?
    By mynickmynick in forum C Programming
    Replies: 0
    Last Post: 05-05-2008, 08:03 AM
  3. pthread mutex problemos
    By cnchybrid in forum C Programming
    Replies: 0
    Last Post: 04-05-2007, 11:20 AM
  4. Troubling compiling with pthread
    By Yasir_Malik in forum Linux Programming
    Replies: 2
    Last Post: 09-30-2003, 07:08 AM