MSH
MSH

Reputation: 429

Reader-Writer in multiple processes C

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

Answers (1)

wangjunwww
wangjunwww

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

Related Questions