Hi there
In my C program i have the main function call a function that creates some pthreads. The program is a TCP/IP daemon
that serves some basic text-based games like tic-tac-toe(yes this is just a programming exercise). Thus it is pre-threaded and each thread serves a game. So the main loop of the program happens in the code of each thread. However because the main loop of these basic games is now called in the thread code, instead of in main where it originally was, functions external to the thread have to get called from within the thread. The games state is a [3][3] char array which was global originally. So now because it's supposed to be a network daemon, i have to use "thread-specific-data" for this [3][3] char array. Here is the main loop from each thread:

So now because the [3][3] char array for the games "state" is in the Thread struct pointed to by tsd then "struct Thread *tsd" has to be global as in the code example above! or has to be passed as an argument to each function. Having global doesn't make any sense because it's thread specific data right? But if i pass "struct Thread *tsd" to the functions the compiler kicks out like 12 errors. The main one is "expected expression" with reference to functions like init_matrix. the call conforms to the prototype namely "init_matrix(struct Thread *tsd)".
I don't know what the recommended/correct solution is. I'm very sorry that i haven't written about this in a concise and general way. I don't know if i understand enough about C to do that yet. Any help would be great. Thank you very much for reading

Please give us a minimal program that you think should work, but that instead fails with the compilation errors described. You showed part of a working single-threaded program and described in English what you changed, but it is far better for us to see what the compiler is given.

Thank you very much for the reply. Here is what i've got so far for a pre-threaded daemon with each thread handling a game of tic-tac-toe. This is not a joke i really am this bad at C programming and i'm sorry that i don't know how to highlight text that's inside the forum "code" tags:

I prefer return 1;, so that the code can be moved into a subroutine without causing unexpected side effects on failure.

methodtwo wrote:

Code:

void thread_make(int i)
{
void *thread_main();

Although block-scope declarations are legal, they are often not a good choice. I suggest making both thread_make and thread_main static, then defining thread_main before thread_create, so that the definition of thread_main doubles as the declaration for it.

The prototype for pthread_create indicates that the thread entry point can take a void*, but you use a thread entry point which takes no arguments. This is legal, but it makes your life harder because it deprives you of the ability to pass thread-specific data into the thread.

Array recvline[] is used uninitialized here. Also, you check for one specific form of failure. If sscanf reads anything, you consider it a success, but I would only consider it a success if it decoded all the required inputs.

Thank you very very much. That is the the most helpful reply i think i've ever had. I was just at the end of a long day and you saved me from, like, reading 4 chapters of K&R. Also in K&R sometimes a combination of advanced topics are treated separately. So it might be hard to find something on "pointers to structures as function arguments" for example. You've already said more than enough. If you don't want to answer the question i've still got that is more than understandable
1) You said that i always over-write tsd, which is a passed parameter, with thread-specific data. I thought i just set it to point to the thread-specific-data then passed a pointer to this thread-specific-data to the needed functions? That is what i needed to do right? So what i erroneously was doing was passing a pointer to a struct of type Thread which over-wrote the pointer(?) or struct(?) that belonged to the thread-specific-data? So to fix it i should just not pass the "struct Thread *tsd to "get_player_move"? So *tsd has to be global? If i'm wrong about this then (in english) what should i have done? Going back to what the original question should have been;Can you have a pointer, that is returned by "pthread_get_specific", declared as a global variable? Thinking about it i guess you can because the array of key structs that hold the destructor function and pointer returned by pthread_get_specific are only pointers to the array of pointers to the malloc'd thread-specific-data, so they should be process wide?. If not how do you pass it to functions that the threads call? I'm sorry this was a long winded and badly thought out as a question!

Thank you for the learned and instructive reply. How do i "officially" "thank" you?
regards

The core problem with your *tsd variable is that it doesn't actually exist. You have to allocate memory for it somewhere before you can pass it to a function. I assume the declaration/calling signature mixup is a copy+paste error.

Maybe explain what you're trying to do here. Remember that the pointer variable tsd itself (other than it's content *tsd) is still passed into the function by value, so changing it will not affect the passed in value. If you want a function to return a pointer you have to pass a pointer-pointer in, or use the return value.

Thanks for the reply. To answer the question: i wanted to have each thread call functions that operated on the games "state". This state is maintained as thread-specific-data, as each player could be writing into the [3][3] char array at the same time that other players wrote/read this array(if it was global). So "here" i was trying to set up a pointer to the thread-specific-data that each thread could pass to the functions it calls, so that each thread could handle a "game". I realise that when each thread called functions then the pointer to the Thread structure should be coded as just tsd and not struct Thread *tsd. Going back to the original question; can you define structs or variables as global and then use the pointer returned from pthread_get_specific as a pointer to these globals so that say struct Thread can be used to hold thread specific data?. If struct Thread is not defined global then the compiler complains that all these functions that the threads call don't know what [b]struct Thread *tsd is! Even though it says in K&R "pointer arguments enable a function to access and change objects in the function that called it. And yes setting up the thread pointer *tsd is now in the main thread function.
[/b]
Thanks

%p outputs the address that the pointer contains (e.g. the actual value of x) while %d outputs the value of the dereferenced pointer (e.g. the assigned value of *x)
Assume the first 4 prints output the following values:

Thanks for being very patient with me. I thought from looking at the code that the final value would be 10 but it's not it's 5. So *x = 5 actually altered a, but, in this case, after the malloc in foo we were no longer dealing with a but a new dynamically generated int so this didn't have any effect on a.
Thank you very much. I think that's enough to be able to let me get it right.
Thanks very much for all the wonderful help