Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`pthread_mutex_trylock` blocks when called by two threads at the same time

I'm using pthread_mutex_trylock to lock the mutex on a struct so that it can only be accessed/modified by a single thread at a given time. If the mutex is already locked I just return from the routine rather than queuing/blocking.

This is a basic outline of my code:

typedef struct {
    pthread_mutex_t m;
} myStruct;

void setupStruct(myStruct* struc) {
    pthread_mutex_init(&struc->m, NULL);
}

void structOp(myStruct* struc) {

    printf("structOp(): Trying to lock\n");

    if(pthread_mutex_trylock(&struc->m) != 0) {
        printf("structOp(): Lock failed\n");
        return;
    } else {
        printf("structOp(): Locked\n");
        // do some stuff to struct
        pthread_mutex_unlock(&struc->m);
    }
}

The struct is initialised once like this:

myStruct* struc = malloc(sizeof(struc));
setupStruct(struc);

However, sometimes when two threads call a routine at the same time both calls to trylock seem to block. I'm assuming this because it prints "Trying to lock" for both threads at the same time, but does not print whether or not the mutex was locked. I was originally having this problem with pthread_mutex_lock so tried the non-blocking version for this reason, but it still seems to block.

This doesn't always happen but when it does it's always the first two calls to the routine. If the first two calls run fine, then subsequent calls also work fine.

Is there any reason this would block? Am I just incorrectly perceiving this blocking due to some other problem? I can post other parts of my code if the problem may lie elsewhere.

like image 847
Matt Avatar asked Apr 21 '12 09:04

Matt


1 Answers

This line is wrong:

    myStruct* struc = malloc(sizeof(struc)); 

It does not alloate enough memory, so you're probably trashing/reusing the memory where you access mutex. Using sizeof(struc) allocates memory for the type of struc , and the type of struc is a myStruct* , so you're only allocating memory enough to hold a pointer (i.e.likely just 4 or 8 bytes)

You should do

    myStruct* struc = malloc(sizeof *struc); 

or

    myStruct* struc = malloc(sizeof(myStruct)); 
like image 99
nos Avatar answered Oct 23 '22 17:10

nos