tags:

views:

448

answers:

2

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);
     }
    }

}
+4  A: 

---- 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.

Chris Lutz
Updated with my actual code, fixed the example too.
dekz
((CarPark*)arg)->parks.size = 1; doesn't seem to make a difference
dekz
They are all for later functionality, I had it implemented, but just stripped it to the basics to find out why it wasn't working and where the problem is. Wall Werror and Wextra, don't provide much help at all. I just used void * as I was testing it with other things, do you think that could be related to the problem?
dekz
It was loosely related to the problem, and not using `void *` would have allowed GCC to catch the error, but it's not directly causing the problem.
Chris Lutz
Nice. Didn't see you had updated. +1
mrduclaw
Oh wow, thank you man, feel a bit noobish at the moment ;)
dekz
@dekz - It happens to all of us at least once.
Chris Lutz
+1  A: 

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;
}
mrduclaw
Definitely +1 for effort. You did as well as you could without seeing the code.
Chris Lutz