I have written a C program that uses two threads for reading and writing. I have declared the variable which are accessed by both the threads as Global. How to avoid the use of global variables in this case.
Please look into following methods of pthread library in C for having exclusive access of Shared Global variables in C:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Similarly, you can look into Semaphores for synchronizing the use of global variables in C threads.
HOw to avoid the use of global variables in this case.
There is no need to avoid global variables. Only thing you have to consider is valid data by some lock mechanism.
Putting all global variables in to a struct is for readability and code control when your project grows.
I suggest you to use mutex lock.. Here is an modified sample code.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
double *a;
double *b;
double sum;
int veclen;
} DOTDATA;
/* Define globally accessible variables and a mutex */
#define NUMTHRDS 4
#define VECLEN 100
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;
void *dotprod(void *arg)
{
/* Define and use local variables for convenience */
int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg;
len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = dotstr.b;
/*
Perform the dot product and assign result
to the appropriate variable in the structure.
*/
mysum = 0;
for (i=start; i<end ; i++)
{
mysum += (x[i] * y[i]);
}
/*
Lock a mutex prior to updating the value in the shared
structure, and unlock it upon updating.
*/
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;
pthread_mutex_unlock (&mutexsum);
pthread_exit((void*) 0);
}
/*
The main program creates threads which do all the work and then
print out result upon completion. Before creating the threads,
the input data is created. Since all threads update a shared structure,
we need a mutex for mutual exclusion. The main thread needs to wait for
all threads to complete, it waits for each one of the threads. We specify
a thread attribute value that allow the main thread to join with the
threads it creates. Note also that we free up handles when they are
no longer needed.
*/
int main (int argc, char *argv[])
{
long i;
double *a, *b;
void *status;
/* Assign storage and initialize values */
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
for (i=0; i<VECLEN*NUMTHRDS; i++)
{
a[i]=1.0;
b[i]=a[i];
}
dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=0;
pthread_mutex_init(&mutexsum, NULL);
for(i=0; i<NUMTHRDS; i++)
{
/*
Each thread works on a different set of data.
The offset is specified by 'i'. The size of
the data for each thread is indicated by VECLEN.
*/
pthread_create(&callThd[i], NULL, dotprod, (void *)i);
}
/* Wait on the other threads */
for(i=0; i<NUMTHRDS; i++)
{
pthread_join(callThd[i], &status);
}
/* After joining, print out the results and cleanup */
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
Do you truly need a shared variable, or do you actually need 2 copies of the same data for each thread? If so, instead of declaring it global, pass it as an argument to the thread at creation.
If it truly needs to be shared, it will need to be protected by a mutex. You can still also do away with the global variable if you bundle the shared variable into a struct along with the mutex and pass it along to the threads as an argument at creation.
I think you're asking how to avoid having your threads accessing globals by passing them their work-data during startup.
Please see the last parameter to pthread_create, which allows you to define a user-defined custom pointer that can be anything you want. Use that to pass data (such as a struct address or even by-value so long as the value can fit in the platform's size of a void pointer.
For example, a parent can send a child thread data by doing such:
Data data;
pthread_create(&thrd, NULL, threadProc, &data);
The child proc would reference this by:
void *threadProc(void *pv)
{
Data *pData = (Data*)pv;
.. use data here...
pthread_exit(NULL);
}
I hope this makes sense, and hope it helps you understand how to pass data to a thread proc, which was what I think your question is.
If you want each thread to have a separate copy of the variable, declare the variables as thread local.
You can make structs. I usually to use a struct called globalArgs where I put all there global variables.
Something like this:
static typedef struct {
int foo;
int baa;
} globalargs;
Or, you can pass all values as parameters to functions that needs of.
Related
My program uses an enum as a semaphore. There are two possible values/states(Because it's a binary semaphore). The program compiles fine. signal() and wait() look logical. Why is program behavior so unpredictable? Even the integer printf is buggy. Here's the code:
#include <stdio.h>
#include <pthread.h>
typedef enum {IN_USE,NOT_IN_USE} binary_semaphore;
binary_semaphore s=NOT_IN_USE;
struct parameters{
int thread_num;
};
void wait(){
while(s==IN_USE);
s=IN_USE;
}
void signal(){
s=NOT_IN_USE;
}
void resource(void *params){
//assuming parameter is a parameters struct.
struct parameters *p=(struct parameters*)params;
wait();
printf("Resource is being used by thread %d\n",(*p).thread_num);
signal();
}
int main(void){
pthread_t threads[4];
struct parameters ps[4]={{1},{2},{3},{4}};
register int counter=0;
while(counter++<4){
pthread_create(&threads[counter],NULL,resource,(void*)&ps[counter]);
}
return 0;
}
What's wrong with my code?
Some of the outputs(Yes, they're different every time):-
(NOTHING)
Resource is being used by thread 32514
Resource is being used by thread 0
Resource is being used by thread 0
Resource is being used by thread 32602
Resource is being used by thread -24547608
Is it a garbage value issue?
What's wrong with my code?
Multiple things, largely discussed in comments already. The most significant one is that your code is rife with data races. That is one of the things that semaphores are often used to protect against, but in this case it is your semaphores themselves that are racy. Undefined behavior results.
Additional issues include
A pthreads thread function must return void *, but yours returns void
You overrun the bounds of your main()'s ps and threads arrays
You do not join your threads before the program exits.
You define functions with the same names as a C standard library function (signal()) and a standard POSIX function (wait()).
Nevertheless, if your C implementation supports the atomics option then you can use that to implement a working semaphore not too different from your original code:
#include <stdio.h>
#include <pthread.h>
#include <stdatomic.h>
// This is used only for defining the enum constants
enum sem_val { NOT_IN_USE, IN_USE };
// It is vital that sem be *atomic*.
// With `stdatomic.h` included, "_Atomic int" could also be spelled "atomic_int".
_Atomic int sem = ATOMIC_VAR_INIT(NOT_IN_USE);
struct parameters{
int thread_num;
};
void my_sem_wait() {
int expected_state = NOT_IN_USE;
// See discussion below
while (!atomic_compare_exchange_strong(&sem, &expected_state, IN_USE)) {
// Reset expected_state
expected_state = NOT_IN_USE;
}
}
void my_sem_signal() {
// This assignment is performed atomically because sem has atomic type
sem = NOT_IN_USE;
}
void *resource(void *params) {
//assuming parameter is a parameters struct.
struct parameters *p = params;
my_sem_wait();
printf("Resource is being used by thread %d\n", p->thread_num);
my_sem_signal();
return NULL;
}
int main(void) {
pthread_t threads[4];
struct parameters ps[4] = {{1},{2},{3},{4}};
for (int counter = 0; counter < 4; counter++) {
pthread_create(&threads[counter], NULL, resource, &ps[counter]);
}
// It is important to join the threads if you care that they run to completion
for (int counter = 0; counter < 4; counter++) {
pthread_join(threads[counter], NULL);
}
return 0;
}
Most of that is pretty straightforward, but the my_sem_wait() function bears a little more explanation. It uses an atomic compare-and-swap to make sure that threads proceed only if they change the value of the semaphore from NOT_IN_USE to IN_USE, with the comparison and conditional assignment being performed as a single atomic unit. Specifically, this ...
atomic_compare_exchange_strong(&sem, &expected_state, IN_USE)
... says "Atomically, compare the value of sem to the value of expected_state and if they compare equal then assign value IN_USE to to sem." The function additionally sets the value of expected_state to the one read from sem if they differ, and returns the result of the equality comparison that was performed (equivalently: returns 1 if the specified value was assigned to sem and 0 if not).
It is essential that the comparison and swap be performed as an atomic unit. Individual atomic reads and writes would ensure that there is no data race, but they would not ensure correct program behavior, because two threads waiting on the semaphore could both see it available at the same time, each before the other had a chance to mark it unavailable. Both would then proceed. The atomic compare and swap prevents one thread reading the value of the semaphore between another's read and update of that value.
Do note, however, that unlike a pthreads mutex or a POSIX semaphore, this semaphore waits busily. That means threads waiting to acquire the semaphore consume CPU while they do, rather than going to sleep as threads waiting on a pthreads mutex do. That may be ok if semaphore access is usually uncontended or if threads never hold it locked very long, but under other circumstances it can make your program much more resource-hungry than it needs to be.
You are encountering race conditions as well as undefined behavior. When you use a regular int as a semaphore in multithreaded applications, there's no guarantee that a process will read a variable's value and modify it before another process is able to read it, which is why you must use a concurrency library designed for your operating system. Furthermore, the function pointer you passed to pthread_create is not the right type, which is undefined behavior.
I replaced your "semaphore" enum with a pointer to pthread_mutex_t which is initialized on the stack of main(), and each thread gets a pointer to it as a member of their struct parameter.
I also changed the definition of void resource(void* params) to void* resource(void *params) as that is a prototype that matches what pthread_create expects as its third parameter.
Your wait() and signal() functions were able to be replaced one-to-one with pthread_mutex_lock() and pthread_mutex_unlock() from pthread.h which you have already included.
#include <stdio.h>
#include <pthread.h>
struct parameters{
int thread_num;
pthread_mutex_t *mutex; //mutex could be global if you prefer
};
void* resource(void *params){ //pthread_create expects a pointer to a function that takes a void* and returns a void*
//assuming parameter is a parameters struct.
struct parameters *p = (struct parameters*)params;
pthread_mutex_lock(p->mutex);
printf("Resource is being used by thread %d\n", p->thread_num);
pthread_mutex_unlock(p->mutex);
return NULL;
}
int main(void){
pthread_t threads[4];
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
struct parameters ps[4]={{1, &mutex},{2, &mutex},{3, &mutex},{4, &mutex}};
for(int counter = 0; counter < 4; ++counter)
pthread_create(&threads[counter], NULL, resource, &ps[counter]);
//Threads should be joined
for(int counter = 0; counter < 4; ++counter)
pthread_join(threads[counter], NULL);
}
This will eliminate the stochasticity that you are experiencing.
The book says that we need to eliminate global or static data to be thread safe. I think that thread safe means that there is no race condition in the program.
However, in the following example, it changes the local veritable "Point pt_ptr" from a non-pointer type to a pointer type"Point *pt_ptr" in order to prevent the race condition. I noticed that he uses "malloc", which means he is going to create something in the heap. And things in the heap are shared by all the threads... Since it creates something that is shared, it prevents the data race BUT will it be thread UNSAFE?
int main(void) {
pthread_t tids[NUM_THREADS];
int i;
Point *pt_ptr;
for (i= 0; i < NUM_THREADS; i++) {
pt_ptr= malloc(sizeof(*pt_ptr));
pt_ptr->x= i;
pt_ptr->y= 3 * i + 2;
pthread_create(&tids[i], NULL, print_point, pt_ptr);
}
It will only be thread unsafe if more than one thread attempts to access the same memory space (variable as an example) without some thread-safety mechanism, such as mutex or semaphore. They are used to provide a blocking mechanism, so that one thread will sit and "wait" until the current owning thread is thru, at which point the 2nd thread will have the ability to access/modify the variable.
Think of them as numbers at the DMV, and you have to wait until yours is called before you can get service.
In this case, each iteration of the loop calls malloc(), creating a new block of memory that is passed only to one thread. (As J. Murray correctly pointed out.) These dynamic variables are not really global at all. You could instead write:
int main(void)
{
pthread_t tids[NUM_THREADS];
for ( int i = 0; i < NUM_THREADS; i++) {
Point * const pt_ptr = malloc(sizeof(*pt_ptr));
assert(pt_ptr); /* TODO: Handle the out-of-memory error. */
pt_ptr->x= i;
pt_ptr->y= 3 * i + 2;
pthread_create(&tids[i], NULL, print_point, pt_ptr);
}
/* ... */
return EXIT_SUCCESS;
}
That version makes clearer that each iteration of pt_ptr is really a separate local variable.
I am trying to create a thread library and my thread is a struct type. Have to follow a certain interface and in that I need to pass the thread by value. For ex: to join on a thread my code is as follows:
int thread_join(thread_t thread, void **status1)
{
printf("Joining thread\n");
long int thId = thread.id;
printf("Thread id: %ld\n", thId);
gtthread_t * thrd = getThreadFromID(thId);
while(thrd->status != EXIT)
{
}
status1 = &(thrd->ret_value);
return 0;
}
And I an passing a struct of type thread_t to this function. My problem is when I see the thread's ID in the calling function, its displayed properly but when I check it in the thread_join function its displayed as 0. The caller function is as follows:
void* caller(void* arg)
{
thread_t th;
thread_create(&th, some_function, NULL);
thread_join(th, NULL);
while(1);
}
Thread create initializes the ID of the thread to a non-zero value and starts the function associated with it.
My thread structure (and other relevant structure is):
typedef enum
{
RUNNING,
WAITING,
CANCEL,
EXIT
} stat;
//Thread
typedef struct
{
ucontext_t t_ctxt;
long int id;
stat status;
void * ret_value;
int isMain;
} thread_t;
int thread_create(thread_t *thread, void *(*start_routine)(void *), void *arg)
{
thread = (thread_t *)malloc(sizeof(thread_t));
thread->id = ++count;
thread->status = RUNNING;
thread->ret_value = NULL;
thread->isMain = 0;
if(getcontext(&(thread->t_ctxt)) == -1)
handle_error("getcontext");
thread->t_ctxt.uc_stack.ss_sp = malloc(SIGSTKSZ);
thread->t_ctxt.uc_stack.ss_size = SIGSTKSZ;
thread->t_ctxt.uc_link = &sched_ctxt;
makecontext(&thread->t_ctxt, (void (*)(void))wrap_func, 2, (void (*)(void))start_routine, arg);
enqueue(gQ, thread);
printf("Thread id: %ld\n", thread->id);
swapcontext(&(curr_thread->t_ctxt),&sched_ctxt);
return 0;
}
Why does this happen? After all, I am passing by value and this should create a copy of the thread with the same values. Thanks.
EDIT:
Basically I am having a queue of threads and there is a scheduler which round-robins. I can post that code here too but I'm sure that's needless and that code works fine.
EDIT2:
I am making a header file from this code and including that header in another file to test it. All my thread_t variables are static. The caller is a function which includes my header file.
What is this line:
thread = (thread_t *)malloc(sizeof(thread_t));
for?
You pass in to thread_create() an address which referrs to a struct thread_t defined in caller() as auto variable.
Doing as you do, you allocate memory to the pointer passed in to thread_create() initialise it and forget the address on return.
The code never writes to the memory being referenced by the address passed in! Besides this it is a memory leak.
To fix this simply remove the line of code quoted above.
You have no mutex guard on thread id getter. Presumably, there is no guard on setter. What can be happening is that the variable is not visible in the other thread yet. And, without a critical section, it may never become visible.
Each variable which is accessed for both read and write from different threads has to be accessed in a critical section (pthread_mutex_lock / unlock).
Another possibility is that you are setting the thread id inside the running thread and you are accessing the variable even before it is set. If you attempt to join immediately after starting a thread it is possible, that the other thread hasn't been run at all yet and the variable is not set.
side note: do yourself a favor and use calloc:)
In caller function,
thread_create(&th, some_function, NULL);
should be
gtthread_create(&th, some_function, NULL);
I have a Tcl main program and I want to create a C thread from it.
I then would need to share information between the two threads: C thread's process frequently updated inputs/outputs.
I see two possible solutions to my problem: (1) port Tcl's Thread Shared Variable to C, but I didn't see any information about it in the TCL-C API. (2) Create Tcl-C linked Variables and use it as arguments during the C thread creation.
The latter idea doesn't seem to work. Here is the C code:
#include <tcl.h>
/*
startRoutine
*/
static void startRoutine (ClientData clientData) {
int *Var;
Var= (int *) clientData;
int locA=0;
int j;
int k;
while (1) {
if (locA=!*Var) {
// Modify Tcl-C shared variable
locA=2 * *Var;
*Var=locA;
for (j=0; j<100; j++){}
} else {
for (k=0; k<100; k++){}
}
}
}
static int
createThreadC_Cmd(
ClientData cdata,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
// Contains the ID of the newly created thread
Tcl_ThreadId id;
// Thread argument
ClientData limitData;
// Transfering global var argument to the created thread
limitData=cdata;
// Thread creation
id=0;
Tcl_CreateThread(&id, startRoutine, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
// Wait thread process, before returning to TCL prog
int i;
int aa;
for (i=0 ; i<10000000 ; i++){
aa=i;
}
// Return thread ID to tcl prog to allow mutex use
Tcl_SetObjResult(interp, Tcl_NewIntObj((int) id));
return TCL_OK;
}
int DLLEXPORT
Behavcextension_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
// Create global Var
int *sharedPtr;
int linkedVar=0;
sharedPtr=&linkedVar;
Tcl_LinkVar(interp, "linkedVar", (char *) sharedPtr, TCL_LINK_INT);
Tcl_CreateObjCommand(interp,
"createThreadC", createThreadC_Cmd, sharedPtr, NULL);
return TCL_OK;
}
Here is the Tcl code:
# linkedVar initial value in Tcl, will be overwritten by C Tcl_LinkVar() function
set linkedVar 98
puts "linkedVar: $linkedVar"
# Thread creation
#------------------
load [file join [pwd] libBehavCextension[info sharedlibextension]]
set threadId [createThreadC]
puts "Created thread $threadId, waiting"
# When Tcl_LinkVar() is called, initiate linkedVar at 2
puts "linkedVar: $linkedVar"
# Function inside thread should modify linkedVar into linkedVar*2
set linkedVar 98
after 5000
puts "linkedVar: $linkedVar"
The terminal output is here:
Main thread ID: tid0xb779b6c0
linkedVar: 98
Created thread -1227252928, waiting
linkedVar: 2
linkedVar: 98
The last result should be 2*98=196. LinkVar creation between Tcl and C is Ok (we get 2 after link creation), but passing LinkVar to the Thread is KO.
Any solution or explanations about why it doesn't work/what to do to solve it are welcome!
The problem remains the same as in the other question. You're allocating the storage for the variable on the C side on the C stack in a function that terminates shortly afterwards. It's Undefined Behavior to refer to that variable (which is linkedVar in Behavcextension_Init) after the termination of the function (Behavcextension_Init). What actually happens is that the actual storage is used for some other function call (doing who knows what) and so the value contained is arbitrary, and changing it can lead to “exciting” behavior.
You're looking to have a variable that exists after Behavcextension_Init finishes, so it must not be allocated in the stack of that function. The simplest method is this:
int DLLEXPORT
Behavcextension_Init(Tcl_Interp *interp)
{
int *sharedPtr;
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
sharedPtr = (int *) Tcl_Alloc(sizeof(int)); // Allocate
*sharedPtr = 0; // Initialize
Tcl_LinkVar(interp, "linkedVar", (char *) sharedPtr, TCL_LINK_INT);
Tcl_CreateObjCommand(interp,
"createThreadC", createThreadC_Cmd, sharedPtr, NULL);
return TCL_OK;
}
Caveats
This leaks memory, as there is no matching Tcl_Free for that Tcl_Alloc. For memory allocated once per process, that's not much of a problem. After all, it's only a few bytes and the OS will reclaim it at exit.
This is unsafe when reading the variable from a different thread than the one where it was written; there's simply no guarantee that it will work. It will probably work as it is just an integer, but you're depending on the hardware to be cooperative. The right thing to do is to allocate a structure containing both the variable and a suitable mutex, and protect the accesses to the variable (whether reads or writes) with the mutex. That in turn requires that you do not use Tcl_LinkVar — it knows nothing about mutex-protected memory — but Tcl_LinkVar is just a wrapper round Tcl_TraceVar that provides a callback that does the coupling between Tcl's variable (see Tcl_GetVar and Tcl_SetVar) and the C variable; writing your own that knows how to do mutex-protection handling as well is not hard. (If you're interested, get the source to Tcl_LinkVar and adapt it yourself; it doesn't use any private API calls.)
i'm working on gcc ,
i'm wondering if this is possible:
I have a function (NOTmain but aLocalFn) and I declare a local variable in it. Then I pass this local argument as a thread argument. is it doable? or there is the chance (depending on what is run first) that the aLocalVar will be lost before threadFunction is run and the reference idxPtr will be pointing to senselessness??
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
return 0;
}
thank you for your help
This code is incorrect. The function aLocalFn may return before the thread function starts executing. And so by the time the thread function reads the local variable, the scope of that variable may have ended.
What can confuse matters is that this code may very well appear to work, at least some of the time. However, it is incorrect and you should use heap allocated memory instead.
your code has a life-time issue with "aLocalVar"
if you just want to pass an integer, here is a non-portable way to do it.
it does not work on some platforms, but you are not likely to encounter those.
void threadFunction ( void * idxptr ) {
int rec_idx = (int) idxptr;
....
}
int rec_idx = returnsRecordIndex();
pthread_create (&thread1, &attr_detached, (void *) &threadFunction, (void *)rec_idx);
It's doable, but it's not done in the code in your question. You will have to add a signal variable to indicate when the new thread is done using the variable. Then your outer function can return.
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t signal = PTHREAD_COND_INITIALIZER;
int done;
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
pthread_mutex_lock(&lock);
done = 1;
pthread_cond_signal(&signal);
pthread_mutex_unlock(&lock);
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
done = 0;
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
pthread_mutex_lock(&lock);
while (!done)
pthread_cond_wait(&signal, &lock);
pthread_mutex_unlock(&lock);
return 0;
}
Note that this example code is itself not thread safe (if multiple threads call aLocalFn).
This does complicate the code, and locking is expensive. So in most cases you're probably better off storing the data in the heap and letting the new thread or pthread_join code free it.
#pizza's answer is what I'd do. Another way for you to do it would be to use malloc/free as #David hinted at. I would certainly do this over the wait loop proposed in other answers here.
int *threadFunction(void *idxPtr){
int rec_idx = *(int *)idxPtr;
// free up our int buffer
free(idxPtr);
...
}
int aLocalFn(){
int aLocalVar = returnsRecordIndex();
// allocate some space for our int
int *intBuf = (int *)malloc(sizeof(int));
*intBuf = aLocalVar;
pthread_create(&thread_id,&attr_detached,threadFunction, intBuf)!=0)
return 0;
}
Whenever you are passing variables to a thread function, it is your job to ensure that the variable remains alive and valid till the thread function is done using it.
In your case aLocalFn() continues to execute simultaneously with the new thread and may even finish execution before the thread, that leaves you with an dangling pointer(pointer pointing to data that may not exist) in thread function since the local variable aLocalVar in the function ceases to exist after function returns.