Reputation: 35
I am trying to create reader and writer threads (5 each) inside an infinite while loop randomly. The writers should wait until all readers are done executing. I am using mutex and condition variables for this purpose.
// Global variables
int readerCount=0, writerCount=0, sharedVariable=1001;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t read_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t write_cond = PTHREAD_COND_INITIALIZER;
The reader threads run the below function
void *readShared(void* param)
{
int shVariable, readers; //To copy and print global variables locally
pthread_mutex_lock(&m);
readerCount++;
while(readerCount > 1)
{
pthread_cond_wait(&read_cond, &m);
}
readerCount--;
readers = readerCount;
shVariable = sharedVariable;
pthread_mutex_unlock(&m);
printf("[Reader]: Value in shared Variable = %d\n", shVariable);
printf("Other \"Reader\" threads present = %d\n", readers);
pthread_mutex_lock(&m);
if(readerCount > 0)
{
pthread_cond_signal(&read_cond);
}
else if(writerCount > 0)
{
pthread_cond_signal(&write_cond);
}
pthread_mutex_unlock(&m);
}
The writer threads run below function:
void *writeShared(void *valueToWrite)
{
//To copy and print global variables
int value = *(int *)(valueToWrite), readers, shVariable;
pthread_mutex_lock(&m);
writerCount++;
while(readerCount > 0 || writerCount > 1)
{
pthread_cond_wait(&write_cond, &m);
}
sharedVariable = value;
readers = readerCount;
shVariable = sharedVariable;
writerCount--;
pthread_mutex_unlock(&m);
printf("[Writer]: Value in shared Variable = %d\n", shVariable);
printf("Value to write = %d\n", value);
printf("Other \"Reader\" threads present = %d\n", readers);
pthread_mutex_lock(&m);
if(readerCount > 0)
{
pthread_cond_signal(&read_cond);
}
else if(writerCount > 0)
{
pthread_cond_signal(&write_cond);
}
pthread_mutex_unlock(&m);
}
The main function:
int main()
{
pthread_t readers[5], writers[5];
int readerIndex=0, writerIndex=0;
while(1)
{
if(5 == readerIndex && 5 == writerIndex)
{
break;
}
if(rand() % 2)
{
if(readerIndex < 5)
{
pthread_create(&readers[readerIndex++], NULL, readShared, NULL);
}
}
else
{
if(writerIndex < 5)
{
pthread_create(&writers[writerIndex++], NULL, writeShared, (void*)((rand() % 1000) + 100));
}
}
}
for(int i=0; i<5; i++)
{
pthread_join(readers[i], NULL);
pthread_join(writers[i], NULL);
}
return 0;
}
I tried running with gdb and obtained following:
Starting program: /home/abhijeet/threads/readWrite
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff77c4700 (LWP 3232)]
[Reader]: Value in shared Variable = 1001
Other "Reader" threads present = 0
[New Thread 0x7ffff6fc3700 (LWP 3233)]
[Thread 0x7ffff77c4700 (LWP 3232) exited]
[New Thread 0x7ffff67c2700 (LWP 3234)]
[Reader]: Value in shared Variable = 1001
Other "Reader" threads present = 0
[New Thread 0x7ffff5fc1700 (LWP 3235)]
[Thread 0x7ffff67c2700 (LWP 3234) exited]
Thread 3 "readWrite" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6fc3700 (LWP 3233)]
0x000055555555494a in writeShared (valueToWrite=0x36d) at PriorityReadWrite.c:13
13 int value = *(int *)(valueToWrite), readers, shVariable;
Upvotes: 3
Views: 87
Reputation: 213917
This line:
pthread_create(&writers[writerIndex++], NULL, writeShared, (void*)((rand() % 1000) + 100));
passes a random integer between 100 and 1099 to the writeShared
function as an argument. In the particular invocation that you debugged with GDB, the random value was 0x36d
, or 877
.
This line:
int value = *(int *)(valueToWrite)
takes passed integer and interprets it as an address of an integer (which it is not), resulting in the segmentation fault.
To fix this, you need to either pass in an address of an actual integer (create an array of int valueToWrite[5]
in main
, and pass &valueToWrite[writerIndex]
to pthread_create
(be careful to increment writerIndex
after you've created the thread).
Alternatively, you can fix the writeShared
to expect an integer instead of an address:
int value = (int)valueToWrite;
Upvotes: 2