1

,This is a rather long question so bear with me. What I'm trying to do is run two processes at the same time. Each process will read a file foo.txt find the last number, increment it and add it back to the file. Since there will be obvious race conditions, I'm trying to implement Peterson's solution to avoid it.

This is all done in an Minix3 environment. I have already defined a variable shared_val which is initialised for every process which runs on the system. And two syscalls, get_sv which returns the value of shared_val and set_sv which sets a user value to the shared_val.

I'm using the values of shared_val of each process to implement the Peterson's solution. I'm also writing the two process ID's to a .txt file config.txt.

The code compiles okay, but it doesn't write to foo.txt. Can someone explain why it could be happening?

#include <stdio.h>
#include <stdlib.h>
#include "sys/types.h"
#include <unistd.h>
#include <strings.h>
#define MAX 10000

int main(int argc, char *argv[])
{
    int yourPID, status = 0, tempid, temp, temp1, i = 0, times;
    int ch[10];
    int a, b, tempo, x, y;
    FILE *fp, *fp1;
    times = atoi((argv[1]));
    ch[i++] = getpid();
    fp = fopen(argv[3], "a");
    while(i>=0)
    {
        fprintf(fp, "%d", ch[1]);
        i--;
    }
    fclose(fp);
    if(yourPID == ch[0])
    {
        set_sv(0, &status);
    }
    if(yourPID == ch[1])
    {
        set_sv(0, &status);
    }
    do 
    {
        yourPID = getpid();
        if(yourPID == ch[0])
        {
            temp = get_sv(ch[0], &status);
        }
        if(yourPID == ch[1])
        {
            temp1 = get_sv(ch[1], &status);
        }
        sleep(1);
        a = ~temp & ~temp1;
        b = temp & temp1;
        sleep(1);
        if(yourPID == ch[0] && ((~a & ~b) == 0))
        {
            char ch1[MAX], len, pos;
            fp1 = fopen(argv[2], "r");
            while(!feof(fp))
            {
                fscanf(fp1,"%s", ch1);
            }
            fclose(fp1);
            len = strlen(ch1);
            pos = len - 1;
            tempo = ch1[pos] + 1;
            fp1 = fopen(argv[2], "a");
            fprintf(fp1, "%c", tempo);
            fclose(fp1);
            tempo = get_sv(yourPID, &status);
            if(tempo == 0)
            {
                tempo = 1;
                set_sv(tempo, &status);
            }
            if(tempo == 1)
            {
                tempo = 0;
                set_sv(tempo, &status);
            }
            sleep(1);
            continue;
        }
        if(yourPID == ch[1] && ((~a & ~b) == 1))
        {
            char ch1[MAX], len, pos;
            fp1 = fopen(argv[2], "r");
            while(!feof(fp1))
            {
                fscanf(fp1, "%s", ch1);
            }
            fclose(fp1);
            len = strlen(ch1);
            pos = len - 1;
            tempo = ch[pos] + 1;
            fp1 = fopen(argv[2], "a");
            fprintf(fp1, "%c", tempo);
            fclose(fp1);
            tempo = get_sv(yourPID, &status);
            if(tempo == 1)
            {
                tempo = 0;
                set_sv(tempo, &Status);
            }
            else
            {
                tempo = 1;
                set_sv(tempo, &status);
            }
            sleep(1);
            continue;
        }
    times = times - 1;
    }while(times > 0);
    return 0;
}

I've added sleep(1) statements throughout the code, to give the other process time to catch up.

The bash commands I've used for this are : ./safe_increment 5 foo.txt config.txt & ./safe_increment 5 foo.txt config.txt

Where 5 is the number of times each process will write to the file.

1 Answers1

1

This shouldn't even compile -- the first line that declares yourPID has an error after the initializer for status, and I don't see the declaration of i. This may be a cut-n-paste error, but there are a lot of subsequent things that it's not clear what you're trying to do, or that simply won't work.

In general, just sleep()ing won't give you reliable interprocess synchronization.

Dave M.
  • 1,496
  • 1
  • 12
  • 30
  • 1
    Sorry, I haven't used Minix for several decades, and I don't know what Peterson's solution is. I do remember that mkdir() is atomic on some systems, so you can use it in lieu of a lock. (One process does mkdir("/tmp/lock-dir"), does the locked operations, and then rmdir("/tmp/lock-dir"). Other processes can spin on mkdir("/tmp/lock-dir") until they succeed, and then they can access the shared resource.) HTH! – Dave M. Mar 27 '16 at 22:06