0

I'm working on an assignment for uni and I'm having trouble defining the global variable Bank in shared memory so that my processes have a shared address. We are exploring race conditions and I'm supposed to have both processes call MakeTransactions() then make use of semaphores to eliminate the race condition. Currently, I keep running into an error of different type (int vs struct) regarding shared memory. Can someone explain what the best way to go about this is? Any suggestions would be helpful. Thanks!

    #include <unistd.h> 
    #include <stdio.h> 
    #include <stdlib.h>  
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/wait.h>

    struct Bank {
        int balance[2];
    };

    struct Bank = *bank;

    // routine for thread execution
    void* MakeTransactions() { 
        int i, j, tmp1, tmp2, rint;
        double dummy;

        for (i=0; i < 100; i++) {  
            rint = (rand()%30)-15; 
            if (((tmp1=bank->balance[0])+rint) >=0 &&
                    ((tmp2=bank->balance[1])-rint)>=0) { 
                bank->balance[0] = tmp1 + rint; 
                for (j=0; j < rint*100; j++) {
                    dummy=2.345*8.765/1.234; // spend time on purpose
                }
                bank->balance[1] = tmp2 - rint; 
            }  
        } 
        return NULL; 
    } 

    int main(int argc, char **argv) { 

        int i;
        void* voidptr = NULL;

            bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
            //check if bank is not NULL
            bank->balance[0] = 100;
            bank->balance[1] = 100;

        pid_t pid;
        srand(getpid()); 

        printf("\nInit balances A:%d + B:%d ==> %d!", 
                bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]); 

        pid=fork();
        if (pid < 0) {
            fprintf(stderr, "Fork failed");
            return 1;
        }
        if (pid == 0) {
            printf("\nChild computing ...");
            MakeTransactions();
            printf("\nChild process complete");
            printf("\nLet's check the balances A:%d + B:%d ==> %d ?= 200",
            bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
            return 0;
        }
        else {
            printf("\nParent computing...\n");
            MakeTransactions();
            wait(NULL);
            printf("\nParent process complete\n");
            printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",
                    bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
            return 0;
        }
        return 0; 
    }
4
  • You got an error message?! Why not add it into the question! Also, your code (with mmap commented out) does not use shared memory. Commented Oct 19, 2017 at 18:37
  • I just compiled your code and did not get any error... only a warning about dummy... Commented Oct 19, 2017 at 19:00
  • Put \n at end not start of printf format control string, or call fflush Commented Oct 19, 2017 at 20:20
  • Please don't completely edit around the scope of your question. Ask a new one when a new problem occurs. Commented Oct 19, 2017 at 21:16

1 Answer 1

1

I would start with a little refactoring of your code, so it would be clear why mmap in your comment cannot work.

Make your struct declaration non-annonymous:

struct Bank {
   int balance[2];
};

And your global: struct Bank bank = {{100,100}};. Now, this bank variable is on stack, which will make switch to mmap harder. Introduce indirection:

struct Bank bankGlobal = {{100, 100}};
struct Bank *bank = &bankGlobal;
...
bank->balance[0] = tmp1 + rint;

Now, bank is a pointer to struct Bank, and it currently points to bankGlobal. You need to change all bank. to bank->. With this code you can switch to mmap solution.

First, you cannot intialize your bank variable using mmap in global space. It has to be in function. Second, you are trying to obtain the size of a pointer to Bank (sizeof *Bank), when you should target entire struct size.

So, change this:

-struct Bank bankGlobal = {{100, 100}};
-struct Bank *bank = &bankGlobal;
+struct Bank *bank;

and in main function:

bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;

Don't forget to munmap when you're done.

About races, you can put POSIX semaphore inside this Bank struct, and protect this transaction, with sem_wait and sem_post.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.