I sucessfully used a static mutex, but i got problem with dynamic version.
In output a variable should be equal to zero..
Please help.
Is any better way to write this?
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#define N 20
int beers=20;
void* drink(void*);
//pthread_mutex_t lockk = PTHREAD_MUTEX_INITIALIZER;
typedef struct st1{
pthread_mutex_t mutex;
int val;
}my_struct_t;
int main(){
pthread_t th[N];
int i;
void* return_val;
my_struct_t *data;
data = malloc(sizeof(my_struct_t));
data->val = 20;
pthread_mutex_init(&data->mutex,NULL);
for(i=0;i<N;i++)
pthread_create(&th[i], NULL, drink, &data);
for(i=0;i<N;i++)
pthread_join(th[i], &return_val);
pthread_mutex_destroy(&data->mutex);
printf("%d\n", beers);
}
void* drink(void* p){
int i;
my_struct_t *data = (my_struct_t *)p;
pthread_mutex_lock(&data->mutex);
beers--;
pthread_mutex_unlock(&data->mutex);
//}
return NULL;
}
Where i got fail? :)
There's a problem here:
pthread_create(&th[i], NULL, drink, &data);
You're passing the address of the pointer data, so a type my_struct_t**, but treating it as a my_struct_t* in the drink function. Remove the & in the caller and the code should work.
Please do some cleanup though. You have unused variables, define N but fail to use it when initializing beer and data->val, you initialize data->val but never use it...
Related
I get "corrupted size vs prev_size" error whenever I allocate a dynamic memory in a thread. Whenever I allocate the memory in main() it works fine. But allocating dynamic memory in thread produces the error.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *fib(void *p);
struct mystruct
{
int *array;
int size;
};
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
struct mystruct obj;
obj.size = atoi(argv[1]);;
pthread_create(&tid, &attr, fib, (void *)&obj);
pthread_join(tid, NULL);
}
void *fib (void *p)
{
struct mystruct *x = (struct mystruct *)p;
x->array = (int *) malloc (x->size);
for (int i=0; i<x->size; i++){
x->array[i] = i;
printf("The array is = %d\n", x->array[i]);
}
}
I've added snapshot for details.
Thanks!
Try with the following line:
x->array = malloc (x->size*sizeof(int));
You need to allocate space for x->size integers. malloc accepts as parameter the number of bytes you need. And for n int you need n times the size in bytes of a single int.
Do not forget to return from the main.
I have just started learning parallel programming using pthreads. So, for the learning purpose I tried sum of two integer arrays parallely. I have declared struct construct with three array variables a, b and c. I want to do addition of a, b and store the result in c.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define MAX 6
struct data {
int a[MAX];
int b[MAX];
int c[MAX];
};
void *addition(void *index) {
struct data *d1 = (struct data *)index;
printf("value of d1 structure=%d\n", d1->a[0]);
}
int main() {
int i, j, t;
struct data *item = NULL;
pthread_t threads[MAX];
item = (struct data *)malloc(sizeof *item);
printf("enter the value for arrray a\n");
for (i = 0; i < MAX; i++) {
scanf("%d", &item->a[i]);
}
printf("enter the value of array b\n");
for (j = 0; j < MAX; j++) {
scanf("%d", &item->b[j]);
}
for (t = 0; t < MAX; t++) {
pthread_create(&threads[t], NULL, addition, (void *)&item);
}
}
Here, as of now I have not added the addition of arrays in the function addition(), because in pthread_create() when I am passing the three arguments with the help of structure, in function addition the variables a and b are not getting copied. Printing a is giving me garbage value. Can anybody help me how to copy the structure variable to the function argument called by pthread_create().
pthread_create Function :
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Kindly note (*arg) is pointer to the arg.
You have created struct data *item as a pointer then you are passing its address i.e. pointer to pointer.
pthread_create(&threads[t], NULL, addition, (void *)&item);
Change the call to
pthread_create(&threads[t], NULL, addition, (void *)item).
I'm having a trouble passing a struct pointer into a function because I'm a bit confused with those pointers and references. I want to modify the thread.thread_num value from the thread_startfunction.
#include <stdio.h>
#include <stdlib.h> //malloc, free
#include <pthread.h>
#define N 5
// void *malloc(size_t);
struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
};
void *thread_start(void *thread)
{
struct thread *my_data;
my_data = (struct thread *)thread;
printf("num T: %i\n", my_data->thread_num);
my_data->thread_num=4;
printf("num T: %i\n", my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread = &pthread_data;
thread->thread_num=2;
pthread_create(&thread->thread_id, NULL, thread_start, (void *)&thread);
printf("num: %i\n",thread->thread_num);
pthread_exit(NULL);
return 0;
}
But the value that print the main doesn't change (2).
And then I want to create an array of thread struct, but I don't know how exactly do that:
I guess it should be something like this:
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread[N-1] = &pthread_data; // I don't know how to manage this.
for(i=0; i<N; i++)
{
thread->thread_num=i;
pthread_create(&thread[i]->thread_id, NULL, thread_start, (void *)&thread[i]);
printf("num %i: %i\n",i,thread[i]->thread_num);
}
pthread_exit(NULL);
return 0;
}
Any thoughts?
I recommend you to read http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf
And here what you wanted:
#define N 5
typedef struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
} ThreadData;
void *thread_start(void *thread)
{
ThreadData *my_data = (ThreadData*)thread;
//there is no guarantee that prints will be in order
// we will use its initial thread->num ,cause it differs for each thread
//plus you will see how threads will behave
int order=my_data->thread_num;
printf("%i) before num T: %i\n",order, my_data->thread_num);
my_data->thread_num=4;
printf("%i) after assignment num T: %i\n",order ,my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
ThreadData thread[N];
for(i=0; i<N; i++)
{
thread[i].thread_num=i;
pthread_create(&(thread[i].thread_id), NULL, thread_start, (void *)(thread+i));
}
//wait for all threads
for (i = 0; i < N; i++)
pthread_join(thread[i].thread_id, NULL);
//print results of each thread
for (i = 0; i < N; i++)
printf(" %i)thread: number %i\n",i,thread[i].thread_num);
return 0;
}
I can see multiple mistakes in your code.
First you have your pointers wrong. In the first example, it is enough to pass &pthread_data to pthread_create, &thread is the address of the thread pointer, so you are passing struct thread ** to your function instead of struct thread *. In the second example you should use (void *) thread[i]. &thread[i] is again struct thread **.
When you want each thread to write to its own thread data, then you should make an array of thread data, so that each thread has its own piece, else you will run into race conditions.
As others have already pointed out, you should call pthread_join before calling printf to ensure that the main thread will wait for all worker threads.
Also note that if you are calling pthread_join from other function that the one that spawned those threads, you have to ensure that the array of tread data will not go out of scope (in this case it would be probably better to use malloc or a global array).
You can't. As soon as main exits, which it does when you call pthread_exit, pthread_data ceases to exist, since it's local to the main function. So it can't be modified.
Is it possible to cast a pointer to an unsigned int, then later cast it back to a pointer? I'm trying to store the pointer to a struct in a pthread_t variable, but I can't seem to get it to work. Here's some snippets of my code (I'm creating a user-level thread management library). When I try to print out the tid of the thread it gives me some long garbage number.
Edit: Never mind, I got it to work.
I changed
thread = (pthread_t) currentThread;
to
*thread = (pthread_t) currentThread;
Figured it was something stupid like that.
Test program:
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, runner, NULL);
pthread_create(&thread2, NULL, runner, NULL);
pthread_join(&thread2, NULL);
My library:
typedef struct queueItem
{
int tid;
ucontext_t context;
int caller;
struct queueItem *joiningOn;
struct queueItem *nextContext;
} queueItem;
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
thread = (pthread_t) currentThread;
}
...
int pthread_join(pthread_t thread, void **retval)
{
queueItem *t = (queueItem *) thread;
if(runningContext->joiningOn != NULL) // Current thread is already waiting on another
return EINVAL;
if(t == NULL) // If thread to join on is invalid
return 0;
fprintf(stdout, "JOINEE: %d\n", t->tid); // Prints weird number
runningContext->caller = JOIN;
runningContext->joiningOn = t;
swapcontext(&(runningContext->context), &scheduleContext);
}
No. On many systems pointer type is bigger than int type. If you have a problem to use pthread_t, ask about it, int is not the answer.
For example, on my machine, the following code:
#include <stdio.h>
int main() {
printf("unsigned int = %lu\n", sizeof(unsigned int));
printf("pointer = %lu\n", sizeof(void*));
return 0;
}
outputs:
unsigned int = 4
pointer = 8
Sure it's possible, if you make sure your unsigned int is the same size as a void* on your system.
If you have some code that's not working, post it.
Edit: You should read about intptr_t, e.g. here: Why / when to use `intptr_t` for type-casting in C?
Hey guys I was wondering if someone could provide a little help.
I've been trying to teach myself pthreads and with that, mutex locks to get threads running together and using the same structure, whilst not reading and writing to bad data.
My problem at the moment is,
From my thread function, if i call a helper function that might look something similar to the following:
void foo(void *arg)
{
Bar *bar = arg;
pthread_mutex_lock(&mutex);
bar->something = 1;
pthread_mutex_unlock(&mutex);
}
This above helper method doesn't seem to "update" the structure.
But if I run the same code in the thread function, the exact same 4 lines, than this seems to work.
What am I doing wrong? Or how do I fix this? If anyone could provide some reading as well that would be perfect.
EDIT: Sorry guys that was a typo in my code.
Here is the actual code I'm using for the structure.
typedef struct {
char *buffer[CAR_PARK_SIZE];
char *arrival_time[CAR_PARK_SIZE];
int keep_running;
int size;
int index;
} CarStorage;
typedef struct {
CarStorage parks;
CarStorage queue;
int busy;
} CarPark;
pthread_mutex_t mutex;
void addCar(char *car, void *arg)
{
CarPark *_cp = arg;
pthread_mutex_lock(&mutex);
printf("Trying to increase size\n");
_cp->parks.size = _cp->parks.size+1;
pthread_mutex_unlock(&mutex);
}
If the same lines in addCar are in the thread function, it will increase the size, if its in this helper function, it won't.
Here is the calling code
void *carpark_t(void *arg)
{
CarPark *_cp = arg;
while (_cp->parks.keep_running)
{
if (_cp->queue.size > 0)
{
addCar(_cp->queue.buffer[_cp->queue.index % MAX_QUEUE], &_cp);
sleep(1);
}
else
{
printf("[C] no cars in queue\n");
sleep(5);
}
}
}
---- Snipped because it no longer applies and didn't work anyway ----
---- Snipped some more because it no longer applies and didn't work anyway ----
And here is your error:
addCar(_cp->queue.buffer[_cp->queue.index % MAX_QUEUE], &_cp);
That &_cp is passing in the address of _cp, which is a pointer to _cp. but _cp is already a pointer, so you're passing in a pointer to a pointer. Either change &_cp to regular _cp, or change void addCar(char *car, void *arg) to void addCar(char *car, void **arg) (and edit addCar() accordingly). Either one should work, but I'd recommend the first one, as it's easier.
What you're doing in addCar with the locking is fine. Your problem is somewhere in the code that you haven't posted. Without access to that, I'm not really sure what your problem is. The following code that I've written works as, I think, intended. If I had to guess what the problem is though, I'd imagine you're not passing around the structure you want to update, but instead copying it over. Hope this helps.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define CAR_PARK_SIZE 10
typedef struct {
char *buffer[CAR_PARK_SIZE];
char *arrival_time[CAR_PARK_SIZE];
int keep_running;
int size;
int index;
} CarStorage;
typedef struct {
CarStorage parks;
CarStorage queue;
int busy;
} CarPark;
pthread_mutex_t mutex;
void *addCar( void *arg)
{
CarPark *_cp = arg;
pthread_mutex_lock(&mutex);
sleep(1);
printf("Trying to increase size\n");
_cp->parks.size = _cp->parks.size+1;
printf("new size: %d\n", _cp->parks.size);
pthread_mutex_unlock(&mutex);
}
#define NUM_THREADS 5
int main()
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
CarPark c;
c.parks.size = 0;
pthread_mutex_init(&mutex, NULL);
for(t=0; t<NUM_THREADS; t++)
{
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, addCar, (void *)&c);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}