简体   繁体   中英

critical sections with eventfd and threads

I have bit of a problem which I can't seem to wrap my head around. I am trying to implement a program (for a uni class) which will have n numbers of trains and m numbers of train sations. However, since my number of stations can be less than the trains that are trying to access them, I would like to add a semaphore like mechanism to critical sections (which would be my train stations) but instead of using semaphores, we have to use eventfd in our os class. Now the problem with my code (so far) seems to be that none of my train threads actually enters a station.

My code would be:

    //Task 1 - sync via eventfd 
//train example : 6 trains and just 3 alleys in a critical section -> train station
// threads = trains will stay = sleep in trainstation and print their current state

#include <sys/eventfd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h> //needed for our in-kernel counter
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/shm.h>

//eventfd: read with EFD_SEMAPHORE will decrease counter by 1 and return 1
// int eventfd(unsigned int initval, int flags);
// without just the previous value and resets to zero
// if eventfd counter is at zero when trying to read, it will block until it turns nonzero again (only if fd is not nonblocking!)
// ssize_t read(int fd, void *buf, size_t count); returns no of bytes if it succeeds
// write adds a number to our 64 bit in-kernel counter
// ssize_t write(int fd, const void *buf, size_t count);
// fd is readable to select, poll, epoll if the counter is non zero
// select - monitors multiple fds until one or more turn "ready"
// poll - waits for an event on a fd 
// epoll - similar to poll - monitors multiple fds to see if i/o is possible (great for large numbers of fds)
// close - required to release the fd - if all fds get closed = resources will be freed by the kernel
// return value = fd used to refer to the eventfd object; unsuccessful = -1

#define fail(msg) {printf(msg); return EXIT_FAILURE;}

struct stationStruct{
    int stations[3];
    uint64_t sem[3];
};

void threadfunction(void* station){
    int n = 3;
    struct stationStruct *st = station;
    int stillWaiting = 1;
    //reads eventfd to check wether train can enter or not
    while(stillWaiting != 0){
        for(int i = 0; i < n && stillWaiting != 0; i++){
            if(read(st->stations[i], (void*) st->sem[i], sizeof(uint64_t)) > 0){
                stillWaiting = 0;
                printf("\n\ntrain no %ld has arrived at train station no %d \n", (long) pthread_self(), i);
                sleep(1);
                printf("train no %ld is ready for departure\n", (long) pthread_self());
                sleep(2);
                printf("train no %ld has left the train station %d\n", (long) pthread_self(), i);
                //writes in order to release the locked eventfd
                write(st->stations[i], (void*) st->sem[i], sizeof(uint64_t));
                break;
                }
                //else{
                //sleep(3);
                //printf("train %ld has failed to enter station %d\n", (long) pthread_self(), i);
            //}
        }
    }
    pthread_exit((void*)pthread_self);
}

int main(int argc, char const *argv[])
{
    int n = 3;
    int m = 4;
    struct stationStruct station;

    //eventfd creation
    for(int i = 0; i < n; i ++){
        if((station.stations[i] = eventfd(1, EFD_SEMAPHORE)) > 0){
            printf("Station %d is open\n", i);
        }
        else{
            fail("could not initialize eventfd for station A\n");
        }
    }

    pthread_t threads[m];
    int returnedValues[m];

    printf("Train Stations 0 - %d are open \n", n);
    for(int i = 0; i < m; i++){
        sleep(1);
        if(pthread_create(&threads[i], NULL, (void*) &threadfunction, (void*)&station) != 0){
            fail("trains did not arrive\n");
        }
    }

    for(int i = 0; i < m; i++){
        pthread_join(threads[i], (void*) &returnedValues[i]);
        printf("Traind %ld left for good\n", (long) threads[i]);
    }

    printf("Train stations are closing now...\n");
    for(int i = 0; i < n; i++){
        printf("sation %d has been closed\n", i);
        close(station.stations[i]);
    }

    printf("Main station has been closed\n");

    return EXIT_SUCCESS;
}

#define _XOPEN_SOURCE

thank you very much for your time and help!

Seems to be a small pointer error?

if(read(st->stations[i], (void*) st->sem[i], sizeof(uint64_t)) > 0){

...

write(st->stations[i], (void*) st->sem[i], sizeof(uint64_t));

Should be

if(read(st->stations[i], &st->sem[i], sizeof(uint64_t)) > 0){

...

write(st->stations[i], &st->sem[i], sizeof(uint64_t));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM