Reputation: 429
I have a C program that parent process create a reader thread and then forks a child process that the child creates multiple writer threads.
Writer threads insert elements into shared buffer correctly but the reader thread doesn't do anything! When I put all reader and writer threads in one process the program works correctly and the reader reads elements from the buffer! Both reader and writer use sem_t
as semaphore and sem_wait
and sem_post
for manage access to buffer.
This is my program pseudo code:
int main()
{
initialize semaphores
create reader_thread(reader code)
fork child process(server)
}
int server()
{
create writer threads(writer code)
}
This is buffer structure:
typedef struct
{
Req_info reqinfo[BUFFER_SIZE];
char chunk[BUFFER_SIZE][MAX_CHUNK_SIZE];
uint64_t chunk_size[BUFFER_SIZE];
int Isnewfile[BUFFER_SIZE]; //1 means new file
int Islastchunk[BUFFER_SIZE]; //1 means last chunk
int ID[BUFFER_SIZE];
int head;
int tail;
int numofelement;
#ifdef SEM_V
sem_t full;
sem_t empty;
sem_t mutex;
#else
pthread_mutex_t mutex;
pthread_cond_t cond_read;
pthread_cond_t cond_write;
#endif
} Buffer;
Buffer *buffer_ptr;
void writer()
{
#ifdef SEM_V
sem_wait(&buffer_ptr->empty);
sem_wait(&buffer_ptr->mutex);
#else
pthread_mutex_lock(&buffer_ptr->mutex);
if((buffer_ptr->tail + 1) % BUFFER_SIZE == buffer_ptr->head)
pthread_cond_wait( &buffer_ptr->cond_write, &buffer_ptr->mutex );
pthread_mutex_unlock(&buffer_ptr->mutex);
pthread_mutex_lock(&buffer_ptr->mutex);
#endif
if ((buffer_ptr->tail + 1) % BUFFER_SIZE != buffer_ptr->head)
{
memmove(buffer_ptr->chunk[buffer_ptr->tail], chunk, chunk_size); //Write chunk into buffer
buffer_ptr->chunk[buffer_ptr->tail][chunk_size] = '\0';
buffer_ptr->chunk_size[buffer_ptr->tail] = chunk_size; //Write chunk size into buffer
buffer_ptr->Isnewfile[buffer_ptr->tail] = Isnewfile;
buffer_ptr->Islastchunk[buffer_ptr->tail] = Islastchunk;
buffer_ptr->reqinfo[buffer_ptr->tail] = reqinfo;
buffer_ptr->ID[buffer_ptr->tail] = ID;
buffer_ptr->tail = (buffer_ptr->tail + 1) % BUFFER_SIZE;
}
#ifdef SEM_V
sem_post(&buffer_ptr->mutex);
sem_post(&buffer_ptr->full);
#else
pthread_cond_signal(&buffer_ptr->cond_write);
pthread_mutex_unlock(&buffer_ptr->mutex);
#endif
}
void reader()
{
#ifdef SEM_V
sem_wait(&buffer_ptr->full);
#endif
if (buffer_ptr->tail != buffer_ptr->head)
{
if(!first){
gettimeofday(&ts, NULL);
first = 1;
}
chunksize = buffer_ptr->chunk_size[buffer_ptr->head]; //Read chunk size from buffer
memmove(chunk, buffer_ptr->chunk[buffer_ptr->head], chunksize); //Read chunk from buffer
chunk[chunksize] = '\0';
Isnewfile = buffer_ptr->Isnewfile[buffer_ptr->head];
Islastchunk = buffer_ptr->Islastchunk[buffer_ptr->head];
reqinfo = buffer_ptr->reqinfo[buffer_ptr->head];
ID = buffer_ptr->ID[buffer_ptr->head];
buffer_ptr->head = (buffer_ptr->head + 1) % BUFFER_SIZE;
}
else{
#ifdef SEM_V
sem_post(&buffer_ptr->empty);
#endif
continue;
}
#ifdef SEM_V
sem_post(&buffer_ptr->empty);
#endif
}
Upvotes: 0
Views: 978
Reputation: 296
There are at least two issues here: 1) whether the sem_t full/empty/mutex
is shared between the parent process and the child process; 2) whether the buffer is shared between the parent process and the child process.
1) Since the child process resides in a separate address space, it no longer shares the same sem_t
with the parent process. So you need to explicitly make those semaphores to be shared. As a result, the reader and writer cannot be properly synchronized. You can refer to this post on how to share semaphore.
2) Similarly due to the copy-on-write mechanism, the reader thread in the parent process and the writer threads in the child process no longer share the same buffer after fork
. So you also need to explicitly share the buffer between the parent and the child. There are several ways to do this.
In your case, since your struct Buffer
contains both semaphores and buffer, you simply need to make it shared, which will resolve both 1) and 2).
Upvotes: 1