Thread: Process based circular buffer not working

  1. #1
    Registered User
    Join Date
    May 2020
    Posts
    29

    Process based circular buffer not working

    I'm converting the program I wrote from the previous thread to use processes instead of threads. Since I got the pthread to work with the help of Salem, I don't need to worry about the looping problems I had before.

    The problem I'm having now is sharing the values across the processes. I'm using mmap() to do this, but it's proving to be a challenge for the buffer and the sharing struct.

    I'm having difficulty initializing share_t as an array and buffer is not properly sharing variables from request_t() to lift() (turning up as zeros from the calloc).

    Can someone help with getting this thing to work, please.

    Here is the code.

    llist.h
    Code:
    #include <stdbool.h>
    
    typedef struct Buffer
    {
        int from;
        int to;
    }buffer_t; //buffer arrary to store from and to values from sim_input
    
    typedef struct Output
    {
        int p; //previous floor
        int rf; //request from
        int rt; //request to
        int total_m[4]; //total movement
        int c; // current position
        int m; //movement
        int total_r[4]; //total requests
    }write_t;
    typedef struct shared_memory
    {
        void* in;
        void* out;
        int id; //name of thread (more relieable than pthread_self())
    }share_t; //Shared memory to be used across functions (Allow multiple arguements in pthread_create)
    lift_sim_B.c
    Code:
    #include <stdio.h>
    #include <stdlib.h> 
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h> 
    #include <semaphore.h>
    #include <sys/mman.h>
    #include <sys/ipc.h>
    #include <sys/shm.h> 
    #include <sys/stat.h>
    #include <fcntl.h> 
    #include "list.h"
    sem_t *full, *empty; //Semaphore mutex intializer
    static int *counter; //number of requests made
    static int size; //buffer size (must only change once at beginning)
                     //Doesn't need to be in shared memory because it will be the same for all processes.
    static int sec; //Time in seconds, needed for lift to execute operation
    static int* length; //Number of values in buffer
                       //Will be shared across processes using mmap.
    static int *in; //index of reader
    static int *out_i; //index of writer
    static buffer_t *A;
    write_t write1; //Used for printing the information from buffer.
    void *lift(void* vargp) //Consumer
    {
        share_t* share = vargp;
        while (true)
        {
            while (*length <= 0)
            {
                sem_wait(&empty);
                printf("Waiting\n");
            }
            sleep(sec);
            printf("lifting information\n");
            int id = ((share_t*)vargp)->id;
            //gather information to print
            if (write1.p == 0) //only for when system begins (Assign Previous to the first record `from` value)
            {
                write1.p = A[*out_i].from;
            }
            write1.rf = A[*out_i].from;
            write1.rt = A[*out_i].to;
            write1.m = (write1.p - A[*out_i].from) + (A[*out_i].to - A[*out_i].from);
            write1.c = A[*out_i].to;
            //Now write the information
            write1.total_r[id] = write1.total_r[id] + 1;
            write1.total_m[id] = write1.total_m[id] + 1;
            fprintf(share->out, "Lift-%d Operation\n"
            "Previous position: Floor %d\n"
            "Request: Floor %d to Floor %d\n"
            "Detail operations:\n"
            "    Go from Floor %d to Floor %d\n"
            "    Go from Floor %d to Floor %d\n"
            "    #movement for this request: %d\n"
            "    #request: %d\n"
            "    Total #movement: %d\n"
            "Current Position: Floor %d\n"
            "\n"
            "----------------------------\n", id, write1.p, write1.rf, write1.rt, write1.p, write1.rf, write1.rf, write1.rt
                , write1.m, write1.total_r[id], write1.total_m[id], write1.c);
            write1.p = write1.c; //for next statement
            *length = *length - 1;
            *out_i = (*out_i + 1) % size;
            if (*length == 0)
            {
                printf("Signalling\n");
                sem_post(&full);
            }
        }
        
        return NULL;
    }
    void *request_t(void *vargp) //producer
    {
        share_t* share = vargp;
        while(1)
        {
            while (*length >= size)
            {
                sem_wait(&full);
                printf("Waiting\n");
            }
            printf("Requesting information\n");
            //read the input line by line and into the buffer
            if (fscanf(share->in, "%d %d\n", &A[*in].from, &A[*in].to) == EOF)
            {
                break;//stop the loop when file is empty
            }
            //If requests go out of bounds, they will be automatically registered as either
            //maximum level or minimum level
            if (A[*in].to > 20)
            {
                A[*in].to = 20;
            }
            else if (A[*in].to < 1)
            {
                A[*in].to = 1;
            }
            else if (A[*in].from > 20)
            {
                A[*in].from = 20;
            }
            else if (A[*in].from < 1)
            {
                A[*in].from = 1;
            }
            //Print buffer information to sim_output
            fprintf(share->out, "New Lift Request from Floor %d to Floor %d \n"
            "Request No %d \n"
            "----------------------------\n", A[*in].from, A[*in].to, * counter = *counter + 1);
            *length = *length + 1;
            *in = (*in + 1) % size;
            if (*length == 1)
            {
                printf("Signalling\n");
                sem_post(&empty);
            }
        }
        return NULL;
    }
    void main(int argc, char *argv[]) // to avoid segmentation fault
    {
        //establish values for use (convert argv to int values)
        if (argc != 3) //Must have both m and t
        {
            perror("Insufficient arguements\n");
            exit(EXIT_FAILURE);
        }
        *counter = 1;
        //Create a shared memory for the file streams
        //it is important the algorithm keeps a consistent stream of values
        share_t *share[4];
        share = mmap(NULL, sizeof * share, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        in = mmap(NULL, sizeof * in, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        out_i = mmap(NULL, sizeof * out_i, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        *in = 0;
        *out_i = 0;
        long arg = strtol(argv[1], NULL, 10);
        size = arg;
        if (size <= 1)
        {
            printf("buffer size too small\n");
            exit(0);
        }
        else
        {
            //allow variables to be shared among processes without duplicates being made
            length = mmap(NULL, sizeof * length, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
            counter = mmap(NULL, sizeof * counter, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
            *length = size;
            *counter = 0;
            //initialize Buffer as empty array and as shared memory.
            A = mmap(NULL, sizeof * A, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
            A = calloc(size, sizeof *A);
        }
        arg = strtol(argv[2], NULL, 10);
        sec = arg; //time required by each lift to serve a request
        if (sec <= 0)
        {
            printf("insufficient time\n");
            exit(0);
        }
        //open files for reading and writing
        FILE *out = fopen("sim_output.txt", "w");
        FILE *in_t = fopen("sim_input.txt", "r");
        if (in == NULL && out == NULL) //Check if files exists before we can use them
        {
            printf("Input file empty\n");
            exit(0);
        }
        for (int i = 0; i < 4; i++)//Load files into share for transporting.
        {
            share[i].in = in_t;
            share[i].out = out;
            share[i].id = i;
        }
        //Create processes
        printf("Creating processes\n");
        int shared_mem_id = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
        full = shmat(shared_mem_id, NULL, 0);
        empty = shmat(shared_mem_id, NULL, 0);
        sem_init(&mutex, 1, 1);
        if (fork() == 0) { // Lift-R Child Proccess 
            
            full = shmat(shared_mem_id, NULL, 0);
            request_t(share);
            shmdt(mutex);
            exit(0);
        }
        if (fork() == 0) { // lift-1 Child Proccess
            empty = shmat(shared_mem_id, NULL, 0);
            lift(share[1]);
            shmdt(mutex);
            exit(0);
        }
        wait(NULL);
        if (fork() == 0) { // lift-2 Child Proccess
            empty = shmat(shared_mem_id, NULL, 0);
            lift(share[2]);
            shmdt(mutex);
            exit(0);
        }
        wait(NULL);
        if (fork() == 0) { // lift-3 Child Proccess
            empty = shmat(shared_mem_id, NULL, 0);
            lift(share[3]);
            shmdt(mutex);
            exit(0);
        }
        wait(NULL);
        int sum_r = write1.total_r[1] + write1.total_r[2] + write1.total_r[3],
            sum_t = write1.total_m[1] + write1.total_m[2] + write1.total_m[3]; //Create total sums of requests and movement
        fprintf(out, "\n"
            "Total number of requests %d \n"
            "Total number of movememts %d \n", sum_r, sum_t); //Print at the very last line after all requests were made
        fclose(in_t);
        fclose(out);
        printf("finished\n");
        exit(0);
    }
    Last edited by Redsam121; 05-16-2020 at 09:27 PM.

  2. #2
    Registered User
    Join Date
    May 2020
    Posts
    29
    I've solved the buffer and share problem, but now having problems with the sem mutex. For example in request_t, even when wait is called, it continues in an infinite loop unless I add a break or exit. Another problem is that the fprintf is not printing to nextline for some reason.

    I noticed in the previous post that there is a lot of mistakes that I didn't clean up. Here is a update on that code:
    Code:
    #include <stdio.h>
    #include <stdlib.h> 
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h> 
    #include <semaphore.h>
    #include <sys/mman.h>
    #include <sys/ipc.h>
    #include <sys/shm.h> 
    #include <sys/stat.h>
    #include <fcntl.h> 
    #include "list.h"
    sem_t *full, *empty; //Semaphore mutex intializer
    static int *counter; //number of requests made
    static int size; //buffer size (must only change once at beginning)
                     //Doesn't need to be in shared memory because it will be the same for all processes.
    static int sec; //Time in seconds, needed for lift to execute operation
    static int *length; //Number of values in buffer
                       //Will be shared across processes using mmap.
    static int *in; //index of reader
    static int *out_i; //index of writer
    static buffer_t *A;
    write_t write1; //Used for printing the information from buffer.
    void *lift(void* vargp) //Consumer
    {
        share_t* share = vargp;
        while (true)
        {
            while (*length <= 0)
            {
                sem_wait(&empty);
                printf("Waiting for request\n");
                exit(0);
            }
            sleep(sec);
            printf("lifting information\n");
            printf("%d %d \n", A[*out_i].from, A[*out_i].to);
            int id = share->id;
            //gather information to print
            if (write1.p == 0) //only for when system begins (Assign Previous to the first record `from` value)
            {
                write1.p = A[*out_i].from;
            }
            write1.rf = A[*out_i].from;
            write1.rt = A[*out_i].to;
            write1.m = (write1.p - A[*out_i].from) + (A[*out_i].to - A[*out_i].from);
            write1.c = A[*out_i].to;
            //Now write the information
            write1.total_r[id] = write1.total_r[id] + 1;
            write1.total_m[id] = write1.total_m[id] + 1;
            fprintf(share->out, "Lift-%d Operation\n"
            "Previous position: Floor %d\n"
            "Request: Floor %d to Floor %d\n"
            "Detail operations:\n"
            "    Go from Floor %d to Floor %d\n"
            "    Go from Floor %d to Floor %d\n"
            "    #movement for this request: %d\n"
            "    #request: %d\n"
            "    Total #movement: %d\n"
            "Current Position: Floor %d\n"
            "\n"
            "----------------------------\n", id, write1.p, write1.rf, write1.rt, write1.p, write1.rf, write1.rf, write1.rt
                , write1.m, write1.total_r[id], write1.total_m[id], write1.c);
            write1.p = write1.c; //for next statement
            *length = *length - 1;
            *out_i = (*out_i + 1) % size;
            if (*length == 0)
            {
                printf("Signalling lift\n");
                sem_post(&full);
            }
        }
        
        return NULL;
    }
    void *request_t(void *vargp) //producer
    {
        share_t* share = vargp;
        while(1)
        {
            while (*length >= size)
            {
                sem_wait(&full);
                printf("Waiting for lift\n");
                exit(0);
            }
            printf("Requesting information\n");
            //read the input line by line and into the buffer
            if (fscanf(share->in, "%d %d\n", &A[*in].from, &A[*in].to) == EOF)
            {
                break;//stop the loop when file is empty
            }
            printf("%d %d \n", A[*in].from, A[*in].to);
            //If requests go out of bounds, they will be automatically registered as either
            //maximum level or minimum level
            if (A[*in].to > 20)
            {
                A[*in].to = 20;
            }
            else if (A[*in].to < 1)
            {
                A[*in].to = 1;
            }
            else if (A[*in].from > 20)
            {
                A[*in].from = 20;
            }
            else if (A[*in].from < 1)
            {
                A[*in].from = 1;
            }
            //Print buffer information to sim_output
            fprintf(share->out, "New Lift Request from Floor %d to Floor %d \n"
            "Request No %d \n"
            "----------------------------\n", A[*in].from, A[*in].to, * counter = *counter + 1);
            *length = *length + 1;
            *in = (*in + 1) % size;
            if (*length == 1)
            {
                printf("Signalling request\n");
                sem_post(&empty);
            }
        }
        return NULL;
    }
    void main(int argc, char *argv[]) // to avoid segmentation fault
    {
        //establish values for use (convert argv to int values)
        if (argc != 3) //Must have both m and t
        {
            perror("Insufficient arguements\n");
            exit(EXIT_FAILURE);
        }
        long arg = strtol(argv[1], NULL, 10);
        size = arg;
        if (size <= 1)
        {
            perror("buffer size too small\n");
            exit(0);
        }
        //allow variables to be shared among processes without duplicates being made
        in = mmap(NULL, sizeof * in, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        out_i = mmap(NULL, sizeof * out_i, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        length = mmap(NULL, sizeof * length, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        counter = mmap(NULL, sizeof * counter, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        *length = 0, *in = 0, *out_i = 0, *counter = 1;
        //initialize Buffer as empty array and as shared memory.
        A = mmap(NULL, sizeof * A, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        for (int i = 0; i < size + 1; i++) //Had to be changed from calloc to for loop due to errors in mmap()
        {                                  //Caused lift to print 0 instead of read values
            A[i].from = 0;
            A[i].to = 0;
        }
        arg = strtol(argv[2], NULL, 10);
        sec = arg; //time required by each lift to serve a request
        if (sec <= 0)
        {
            perror("insufficient time\n");
            exit(0);
        }
        //open files for reading and writing
        FILE *out = fopen("sim_output.txt", "w");
        FILE *in_t = fopen("sim_input.txt", "r");
        if (in == NULL && out == NULL) //Check if files exists before we can use them
        {
            perror("Input file empty\n");
            exit(0);
        }
        //Create a shared memory for the file streams
        //it is important the algorithm keeps a consistent stream of values
        share_t *share[4];
        for (int i = 0; i < 4; i++)//Load files into share for transporting.
        {
            share[i] = mmap(NULL, sizeof * share, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
            share[i]->in = in_t;
            share[i]->out = out;
            share[i]->id = i;
        }
        //Create processes
        printf("Creating processes\n");
        int shared_mem_id = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
        full = shmat(shared_mem_id, NULL, 0);
        empty = shmat(shared_mem_id, NULL, 0);
        sem_init(&full, 1, 1);
        sem_init(&empty, 1, 1);
        if (fork() == 0) { // Lift-R Child Proccess
            full = shmat(shared_mem_id, NULL, 0);
            empty = shmat(shared_mem_id, NULL, 0);
            request_t(share[0]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        wait(NULL);
        if (fork() == 0) { // lift-1 Child Proccess
            empty = shmat(shared_mem_id, NULL, 0);
            full = shmat(shared_mem_id, NULL, 0);
            lift(share[1]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        wait(NULL);
        if (fork() == 0) { // lift-2 Child Proccess
            empty = shmat(shared_mem_id, NULL, 0);
            full = shmat(shared_mem_id, NULL, 0);
            lift(share[2]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        wait(NULL);
        if (fork() == 0) { // lift-3 Child Proccess
            empty = shmat(shared_mem_id, NULL, 0);
            full = shmat(shared_mem_id, NULL, 0);
            lift(share[3]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        wait(NULL);
        int sum_r = write1.total_r[1] + write1.total_r[2] + write1.total_r[3],
            sum_t = write1.total_m[1] + write1.total_m[2] + write1.total_m[3]; //Create total sums of requests and movement
        fprintf(out, "\n"
            "Total number of requests %d \n"
            "Total number of movememts %d \n", sum_r, sum_t); //Print at the very last line after all requests were made
        fclose(in_t);
        fclose(out);
        printf("finished\n");
        exit(1);
    }

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    int shared_mem_id = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
    full = shmat(shared_mem_id, NULL, 0);
    empty = shmat(shared_mem_id, NULL, 0);
    You want two semaphores, you need to allocate space for two semaphores.

    Please stop using void main.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    May 2020
    Posts
    29
    Okay I've changed the size to (2 * sizeof(sem_t)) which should double the size for two semaphores. I've also changed void main to int main.

  5. #5
    Registered User
    Join Date
    May 2020
    Posts
    29
    When the buffer is full and calls sem_wait(&full); it goes into an infinite loop. I only want the while(1) to go until the sem_wait is called, then go to lift and return to request_t. It only stops when I add exit(0) after sem_wait, but that stops the lifts from loop.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Post the latest code please.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    May 2020
    Posts
    29
    I've been running diagnostics on it and I found that it doesn't return to lift-R when the buffer is empty and instead goes to lift-2 then lift-3. I'm positive it's to do with the sem mutexs.
    Code:
    #include <stdio.h>
    #include <stdlib.h> 
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h> 
    #include <semaphore.h>
    #include <sys/mman.h>
    #include <sys/ipc.h>
    #include <sys/shm.h> 
    #include <sys/stat.h>
    #include <fcntl.h> 
    #include "list.h"
    sem_t *full, *empty; //Semaphore mutex intializer
    static int *counter; //number of requests made
    static int size; //buffer size (must only change once at beginning)
                     //Doesn't need to be in shared memory because it will be the same for all processes.
    static int sec; //Time in seconds, needed for lift to execute operation
    static int *length; //Number of values in buffer
                       //Will be shared across processes using mmap.
    static int *in; //index of reader
    static int *out_i; //index of writer
    static buffer_t *A;
    static write_t *write1; //Used for printing the information from buffer.
    void *lift(void* vargp) //Consumer
    {
        share_t* share = vargp;
        while (true)
        {
            while (*length <= 0)
            {
                sem_wait(&empty);
                printf("Waiting for request\n");
                exit(0);
            }
            sleep(sec);
            printf("lifting information\n");
            printf("%d %d \n", A[*out_i].from, A[*out_i].to);
            int id = share->id;
            //gather information to print
            if (write1->p == 0) //only for when system begins (Assign Previous to the first record `from` value)
            {
                write1->p = A[*out_i].from;
            }
            write1->rf = A[*out_i].from;
            write1->rt = A[*out_i].to;
            write1->m = (write1->p - A[*out_i].from) + (A[*out_i].to - A[*out_i].from);
            write1->c = A[*out_i].to;
            //Now write the information
            write1->total_r[id] = write1->total_r[id] + 1;
            write1->total_m[id] = write1->total_m[id] + write1->m;
            fprintf(share->out, "Lift-%d Operation\r\n"
            "Previous position: Floor %d\r\n"
            "Request: Floor %d to Floor %d\r\n"
            "Detail operations:\r\n"
            "    Go from Floor %d to Floor %d\r\n"
            "    Go from Floor %d to Floor %d\r\n"
            "    #movement for this request: %d\r\n"
            "    #request: %d\r\n"
            "    Total #movement: %d\r\n"
            "Current Position: Floor %d\r\n"
            "\r\n"
            "----------------------------\r\n", id, write1->p, write1->rf, write1->rt, write1->p, write1->rf, write1->rf, write1->rt
                , write1->m, write1->total_r[id], write1->total_m[id], write1->c);
            write1->p = write1->c; //for next statement
            *length = *length - 1;
            *out_i = (*out_i + 1) % size;
            if (*length == 0)
            {
                printf("Signalling lift\n");
                sem_post(&full);
            }
        }
        
        return NULL;
    }
    void *request_t(void *vargp) //producer
    {
        share_t* share = vargp;
        while(1)
        {
            while (*length >= size)
            {
                sem_wait(&full);
                printf("Waiting for lift\n");
                exit(0);
            }
            printf("Requesting information\n");
            //read the input line by line and into the buffer
            if (fscanf(share->in, "%d %d\n", &A[*in].from, &A[*in].to) == EOF)
            {
                exit(1);//stop the loop when file is empty
            }
            printf("%d %d \n", A[*in].from, A[*in].to);
            //If requests go out of bounds, they will be automatically registered as either
            //maximum level or minimum level
            if (A[*in].to > 20)
            {
                A[*in].to = 20;
            }
            else if (A[*in].to < 1)
            {
                A[*in].to = 1;
            }
            else if (A[*in].from > 20)
            {
                A[*in].from = 20;
            }
            else if (A[*in].from < 1)
            {
                A[*in].from = 1;
            }
            //Print buffer information to sim_output
            fprintf(share->out, "New Lift Request from Floor %d to Floor %d \r\n"
            "Request No %d \r\n"
            "----------------------------\r\n", A[*in].from, A[*in].to, * counter = *counter + 1);
            *length = *length + 1;
            *in = (*in + 1) % size;
            if (*length == 1)
            {
                printf("Signalling request\n");
                sem_post(&empty);
            }
        }
        return NULL;
    }
    int main(int argc, char *argv[]) // to avoid segmentation fault
    {
        //establish values for use (convert argv to int values)
        if (argc != 3) //Must have both m and t
        {
            perror("Insufficient arguements\n");
            exit(EXIT_FAILURE);
        }
        long arg = strtol(argv[1], NULL, 10);
        size = arg;
        if (size <= 1)
        {
            perror("buffer size too small\n");
            exit(0);
        }
        //allow variables to be shared among processes without duplicates being made
        in = mmap(NULL, sizeof * in, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        out_i = mmap(NULL, sizeof * out_i, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        length = mmap(NULL, sizeof * length, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        counter = mmap(NULL, sizeof * counter, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        write1 = mmap(NULL, sizeof * write1, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        *length = 0, *in = 0, *out_i = 0, *counter = 1;
        //initialize Buffer as empty array and as shared memory.
        A = mmap(NULL, sizeof * A, PROT_READ | PROT_WRITE,
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        for (int i = 0; i < size + 1; i++) //Had to be changed from calloc to for loop due to errors in mmap()
        {                                  //Caused lift to print 0 instead of read values
            A[i].from = 0;
            A[i].to = 0;
        }
        arg = strtol(argv[2], NULL, 10);
        sec = arg; //time required by each lift to serve a request
        if (sec <= 0)
        {
            perror("insufficient time\n");
            exit(0);
        }
        //open files for reading and writing
        FILE *out = fopen("sim_output.txt", "w");
        FILE *in_t = fopen("sim_input.txt", "r");
        if (in == NULL && out == NULL) //Check if files exists before we can use them
        {
            perror("Input file empty\n");
            exit(0);
        }
        //Create a shared memory for the file streams
        //it is important the algorithm keeps a consistent stream of values
        share_t *share[4];
        for (int i = 0; i < 4; i++)//Load files into share for transporting.
        {
            share[i] = mmap(NULL, sizeof * share, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
            share[i]->in = in_t;
            share[i]->out = out;
            share[i]->id = i;
        }
        //Create processes
        printf("Creating processes\n");
        int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT);//must allocate space for two semaphores
        sem_init(&full, 1, 1);
        sem_init(&empty, 1, 1);
        full = shmat(shared_mem_id, NULL, 0);
        empty = shmat(shared_mem_id, NULL, 0);
        pid_t Lift_R = fork();
        if (Lift_R == 0) { // Lift-R Child Proccess
            full = shmat(shared_mem_id, NULL, 0);
            empty = shmat(shared_mem_id, NULL, 0);
            request_t(share[0]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        else if (Lift_R == -1)//Error detection
        {
            perror("could not wait for child\n");
            exit(0);
        }
        wait(NULL);
        pid_t lift_1 = fork();
        if (lift_1 == 0) { // lift-1 Child Proccess
            full = shmat(shared_mem_id, NULL, 0);
            empty = shmat(shared_mem_id, NULL, 0);
            printf("A\n");
            lift(share[1]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        else if (lift_1 == -1)
        {
            perror("could not wait for child\n");
            exit(0);
        }
        wait(NULL);
        pid_t lift_2 = fork();
        if (lift_2 == 0) { // lift-2 Child Proccess
            full = shmat(shared_mem_id, NULL, 0);
            empty = shmat(shared_mem_id, NULL, 0);
            printf("B\n");
            lift(share[2]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        else if (lift_2 == -1)
        {
            perror("could not wait for child\n");
            exit(0);
        }
        wait(NULL);
        pid_t lift_3 = fork();
        if (lift_3 == 0) { // lift-3 Child Proccess
            full = shmat(shared_mem_id, NULL, 0);
            empty = shmat(shared_mem_id, NULL, 0);
            printf("C\n");
            lift(share[3]);
            shmdt(full);
            shmdt(empty);
            exit(0);
        }
        else if (lift_3 == -1)
        {
            perror("could not wait for child\n");
            exit(0);
        }
        wait(NULL);
        sem_destroy(&full);
        sem_destroy(&empty);
        int sum_r = write1->total_r[1] + write1->total_r[2] + write1->total_r[3],
            sum_t = write1->total_m[1] + write1->total_m[2] + write1->total_m[3]; //Create total sums of requests and movement
        fprintf(out, "\r\n"
            "Total number of requests %d \r\n"
            "Total number of movememts %d \r\n", sum_r, sum_t); //Print at the very last line after all requests were made
        fclose(in_t);
        fclose(out);
        printf("finished\n");
        exit(1);
    }

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Are you getting lots of warnings like this?
    main.c:107:22: warning: passing argument 1 of ‘sem_wait’ from incompatible pointer type [-Wincompatible-pointer-types]
    sem_wait(&full);

    Code:
        int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT);//must allocate space for two semaphores
        sem_init(&full, 1, 1);
        sem_init(&empty, 1, 1);
        full = shmat(shared_mem_id, NULL, 0);
        empty = shmat(shared_mem_id, NULL, 0);
    Both full and empty are pointing to the same place.

    And you init before setting the pointers.
    Code:
        int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT);//must allocate space for two semaphores
        sem_t *two_sems = shmat(shared_mem_id, NULL, 0);
        full = &sems[0];
        empty = &sems[1];
        sem_init(full, 1, 1);
        sem_init(empty, 1, 1);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    May 2020
    Posts
    29
    Yes I am getting those errors. However the code now stops immediately at sem_init(full, 1, 1);.

    By the way shouldn't full = &sems[0]; be full = &two_sems[0];?
    Last edited by Redsam121; 05-17-2020 at 04:52 AM.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > By the way shouldn't full = &sems[0]; be full = &two_sems[0];?
    Yes
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    May 2020
    Posts
    29
    I'm no longer getting those warnings on compiling. But the code just suddenly stops at sem_init(full, 1, 1);.
    Code:
    int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT);//must allocate space for two semaphores
        sem_t *two_sems = shmat(shared_mem_id, NULL, 0);
        full = &two_sems[0];
        empty = &two_sems[1];
        sem_init(full, 1, 1);//stops here
        sem_init(empty, 1, 1);

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Did you check for errors?
    Code:
    int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT);
        if(errno) perror("E1");
        sem_t *two_sems = shmat(shared_mem_id, NULL, 0);
        if(errno) perror("E2");
        full = &two_sems[0];
    
    
    
    Breakpoint 1, main () at main.c:296
    296	int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT);
    (gdb) n
    297	    if(errno) perror("E1");
    (gdb) 
    298	    sem_t *two_sems = shmat(shared_mem_id, NULL, 0);
    (gdb) 
    299	    if(errno) perror("E2");
    (gdb) 
    E2: Permission denied
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    May 2020
    Posts
    29
    Error reports
    E1: Function not implemented
    E2: Invalid arguement

    shared_mem_id is printing as -1. I'm using cygwin to test this code since I'm using windows.
    Last edited by Redsam121; 05-17-2020 at 07:18 AM.

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > I'm using cygwin to test this code since I'm using windows.
    Yeah, a lot of this stuff isn't going to work in cygwin.

    You'll be better off installing WSL or using VirtualBox for that authentic Linux experience.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Registered User
    Join Date
    May 2020
    Posts
    29
    Is there any other option for windows 8

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pthread Circular buffer not looping, need help!
    By Redsam121 in forum C Programming
    Replies: 28
    Last Post: 05-15-2020, 10:24 PM
  2. Circular buffer - console crashing
    By High Voltage in forum C++ Programming
    Replies: 10
    Last Post: 02-26-2017, 08:59 AM
  3. Circular Buffer using Virtual Memory
    By SMurf in forum Windows Programming
    Replies: 5
    Last Post: 03-26-2013, 07:05 PM
  4. Circular buffer - logic difficulty
    By erasm in forum C Programming
    Replies: 2
    Last Post: 10-05-2009, 01:08 PM
  5. Circular Buffer
    By parisframe in forum C Programming
    Replies: 11
    Last Post: 09-16-2009, 11:05 PM

Tags for this Thread