Please l have single processor C code and I need to write it in multiprocessor with mutul exclusion.
Can any ony one help me.
I have uploaded C code as attachement

Recommended Answers

All 7 Replies

Please post the code directly, and describe the problems you are having.

Hi,
I want this code to run on multiprossesor operating system with mutual exclusion

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <errno.h>
#include <sys/time.h>

#define DATASIZE (10<<20)
bool lock = false;

int main()
{
    double A[200][200];
    double B[200][200];
    double C[200][200];
    int i, j, k, m; 
    int outfile, result, count; 
    int counter = 0;
    unsigned seed;

    struct timeval before, after;

    char *buff;

    buff = (char *)malloc(sizeof(char)*(10<<20));

    srandom(seed);




bool TestAndTest(bool *target)
{
bool rv = *target;
*target = true;
return rv;
}

    for (i=0; i<200; i++)
    for (j=0; j<200; j++) {
        A[i][j] = random()/100.0;
        B[i][j] = random()/100.0;
    }

    gettimeofday(&before, NULL);

pid_t pid ;
pid = fork () ;

if (pid == -1) {
    perror ("fork faild") ;
     exit(EXIT_FAILURE);
}

else

if (pid >=0) {
if (pid == 0) {


     for (m=0 ; m<10 ; m++)
{
/* I/O */ /* STARTING I/O CRITICAL SECTION */
do {
while(TestAndSet(&lock))
;

    printf("I/O process iteration was allowed to start \n");
    outfile = open("testfile", O_RDWR|O_CREAT|O_APPEND, 0777);
    if (outfile <= 0)
        perror("Error opening file\n");
    else {
        result = write(outfile, buff, DATASIZE);
        if (result <= 0)
        perror("Error writing file\n");
    }
    close(outfile);

    counter++;
    printf("I/O process iteration is finished \n");
    /* ENDING I/O CRITICAL SECTION */
}
free(buff);
lock = false;
}
else {for (m=0 ; m < 10; m++) {
    /* Computation */ /* STARTING COMPUTATION CRITICAL SECTION */ 
    printf("Comuptation process iteration was allowed to start \n");
    for (i=0; i<200; i++)
        for (j=0; j<200; j++) {
        C[i][j] = 0;
        for (k=0; k<200; k++)
            C[i][j] += A[i][k]*B[k][j];
        }

    counter++;
    printf("Comuptation process iteration is finished \n");
wait();
    /* ENDING COMPUTATION CRITICAL SECTION */


    }}
}

}while(true);

    gettimeofday(&after, NULL);

    count = (after.tv_sec - before.tv_sec) * 1e6;
    count += (after.tv_usec - before.tv_usec);

    printf("Total time in usec: %d\n", count);
    printf("Counter final value: %d\n", counter);
    return 0;
};

OK, first off, this code as posted isn't valid; you have the TestAndTest() function (which I assume is actually supposed to be TestAndSet(), but that's an aside) inside the main() function, which is an error (C does not allow for nested functions). I assume it is a quirk of cutting and pasting the code her, however.

I would recomend a more consistent indent style as well; here is your code re-indented (using Astyle set to Allman style) for readability:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>

#define DATASIZE (10<<20)
bool lock = false;


bool TestAndSet(bool *target)
{
    bool rv = *target;
    *target = true;
    return rv;
}


int main()
{
    double A[200][200];
    double B[200][200];
    double C[200][200];
    int i, j, k, m; 
    int outfile, result, count; 
    int counter = 0;
    unsigned seed;

    struct timeval before, after;

    char *buff;

    buff = (char *)malloc(sizeof(char)*(10<<20));

    srandom(seed);


    for (i=0; i<200; i++)
        for (j=0; j<200; j++)
        {
            A[i][j] = random()/100.0;
            B[i][j] = random()/100.0;
        }

    gettimeofday(&before, NULL);

    pid_t pid ;
    pid = fork () ;

    if (pid == -1)
    {
        perror ("fork faild") ;
        exit(EXIT_FAILURE);
    }

    else

        if (pid >=0)
        {
            if (pid == 0)
            {
                for (m=0 ; m<10 ; m++)
                {
/* I/O */ /* STARTING I/O CRITICAL SECTION */
                    do 
                    {
                        while(TestAndSet(&lock))
                            ;

                        printf("I/O process iteration was allowed to start \n");
                        outfile = open("testfile", O_RDWR|O_CREAT|O_APPEND, 0777);
                        if (outfile <= 0)
                            perror("Error opening file\n");
                        else 
                        {
                            result = write(outfile, buff, DATASIZE);
                            if (result <= 0)
                                perror("Error writing file\n");
                        }
                        close(outfile);

                        counter++;
                        printf("I/O process iteration is finished \n");
                        /* ENDING I/O CRITICAL SECTION */
                    }
                    free(buff);
                    lock = false;
                }
                else
                {
                    for (m=0 ; m < 10; m++)
                    {
                        /* Computation */ /* STARTING COMPUTATION CRITICAL SECTION */ 
                        printf("Comuptation process iteration was allowed to start \n");
                        for (i=0; i<200; i++)
                            for (j=0; j<200; j++) 
                            {
                                C[i][j] = 0;
                                for (k=0; k<200; k++)
                                    C[i][j] += A[i][k]*B[k][j];
                            }

                        counter++;
                        printf("Comuptation process iteration is finished \n");
                        wait();
                        /* ENDING COMPUTATION CRITICAL SECTION */


                    }
                }
            }

        } while(true);

    gettimeofday(&after, NULL);

    count = (after.tv_sec - before.tv_sec) * 1e6;
    count += (after.tv_usec - before.tv_usec);

    printf("Total time in usec: %d\n", count);
    printf("Counter final value: %d\n", counter);
    return 0;
}  

Getting to the problems with the code itself, I will start by explaining that TestAndSet() as it is written will not work; in fact, you cannot write a workable mutual exclusion function in pure C at all, at least not one that will work on multiple platforms. C does not guarantee any operation to be atomic, period. You simply cannot know how many instructions the compiler will generate for any given operation, so even a simple assignment cannot be assumed to be atomic. In this case, your code will - not may be will - require at minimum five instructions, since it involves two distinct pointer dereferences, an assignment to memory, and a function return. The possibility of a clock interrupt (and possibly a process switch) in the middle of the operation means that it simply isn't workable as a mutual exclusion primitive as written.

It can be made to work, if you can block interrupts and (since you mean this to work on multiple processors) lock access to the memory bus while in the critical section - but that would require an assembly language operation, either inline or as a separately assembled procedure. Since most processors have at least one guaranteed-atomic instruction that is specifically intended for mutual exclusion (e.g., XCHG with the LOCK modifier on the x86 architecture), it would make more sense to simply use the one appropriate to your CPU.

However, that's not even an issue if you know the OS you are running under, as any of them will have a standard mutex primitive for you to use already. I am assuming you are using a Unixoid system of some sort, given the use of the <unistd.h> header and other Unix/Linux specific headers, so applying one of the standard Unix functions should be possible. In this case, I would recommend dropping the idea of multiple processes (the per-process overhead is rather high, cutting into the advantages of multiprocessing in the first place) and use the pthread library instead.

In any case, you didn't say which part of the code you want to parallelize. If you want to apply multiprocessing to the individual operations on the matrix elements, well, unless you have access to a massively parallel supercomputer, I would forget it. Unless there are at least as many CPUs as there are threads/processes being computed, something like this will run slower if parallelized, due to the process switching overhead. Furthermore, even that won't be practical unless the operations are lengthy enough that the speedup from parallel operations is greater than the overhead of spinning off the required number of threads, which isn't the case in this instance. Finally, since each thread would have to operate on a common array data structure (even if each one works on only a single element of it), the synchronization overhead would swamp the advantages of using multiple CPUs. Trying to parallelize 400000 operations is simply not feasible on stock hardware at this time.

Schol-R-LEA beet me to the mark with his response. Your original post is not valid C code. You can use semaphores to enable a mutual-exclusion behavior, but all the processes that need to access the common service/data will have to utilize the semaphore in order for this to work. I have had to do this in the past for C programs to safely access shared memory.

I want to make the computation part as parent process and the input/output as the child if it is possible. Then allows mutual exclusion using Testandset.

Hi ,
Sorry Brothers,
here is my code where i tried to separate the computation into a process and the I/O into another process. when i do compile there is no error, but when i run it; it goes spinning and spinning without stoping..
even i declared the lock variabe in a separate header file like this:
extern bool lock;
bool lock= false;
and included as #include"shared.h"

#include <sys/types.h> /* pid_t */
#include <sys/wait.h>  /* waitpid */
#include <stdio.h>     /* printf, perror */
#include <stdlib.h>    /* exit */
#include <unistd.h>    /* _exit, fork */
 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <errno.h>
#include <sys/time.h>
#include <stdbool.h>

#define DATASIZE (10<<20)
bool lock= false;

bool TestAndSet(bool *target)
{
bool rv = *target;
*target = true;
return rv;
}



int main()
{
int counter= 0;

    double A[200][200];
    double B[200][200];
    double C[200][200];
    int i, j, k, m; 
    int outfile, result, count; 
    unsigned seed;

    struct timeval before, after;

    char *buff;

    buff = (char *)malloc(sizeof(char)*(10<<20));

    srandom(seed);
/* ==================================================================*/

    for (i=0; i<200; i++)
    for (j=0; j<200; j++) {
        A[i][j] = random()/100.0;
        B[i][j] = random()/100.0;
    }

/* ==================================================================*/

    gettimeofday(&before, NULL);

   pid_t pid;

   pid = fork();

   if (pid ==-1) {
      /*
       * When fork() returns -1, an error happened.
       */
      perror("fork failed");
      exit(EXIT_FAILURE);
   }

/* ================================================================*/

  else

   if(pid >=0)
   {

/* =================================================================*/
   if (pid == 0) {
      /*
       * When fork() returns 0, we are in the child process.
       */
gettimeofday(&before, NULL);

 for (m=0 ; m < 10; m++) {


while(TestAndSet(&lock))

printf("spinning");

    /* Computation */ /* STARTING COMPUTATION CRITICAL SECTION */ 

    printf("Comuptation process iteration was allowed to start \n");
    for (i=0; i<200; i++)
        for (j=0; j<200; j++) {
        C[i][j] = 0;
        for (k=0; k<200; k++)
            C[i][j] += A[i][k]*B[k][j];
           }

        counter++;
    printf("Comuptation process iteration is finished \n");

    /* ENDING COMPUTATION CRITICAL SECTION */





      } /*===computation iterations=======for*/
lock = false;   

}  /* ================if pid == 0 ==================*/






   else {

      /*
       * When fork() returns a positive number, we are in the parent process
       * and the return value is the PID of the newly created child process.
       */

for (m=0 ; m < 10; m++)
          {

while(TestAndSet(&lock))

printf("spinning");

/*======================critical section =========================*/

    /* I/O */ /* STARTING I/O CRITICAL SECTION */
    printf("I/O process iteration was allowed to start \n");

           outfile = open("testfile", O_RDWR|O_CREAT|O_APPEND, 0777);
           if (outfile <= 0)
            perror("Error opening file\n");
           else {
            result = write(outfile, buff, DATASIZE);
            if (result <= 0)
           perror("Error writing file\n");
                       }   /* if*/



          close(outfile);
          counter++;
    printf("I/O process iteration is finished \n");

}
/* ENDING I/O CRITICAL SECTION */

int status;
   (void)waitpid(0, &status, 0);
   // wait(NULL);
         // } /* for */
//} /*else*/

           free(buff);



    gettimeofday(&after, NULL);

    count = (after.tv_sec - before.tv_sec) * 1e6;
    count += (after.tv_usec - before.tv_usec);


    printf("Total time in usec: %d\n", count);
printf("Counter final value: %d\n", counter);


  } /* parent*/

 } /* parent & child*/

return 0;
}

Would mind explaining why you want to separate them in this manner? It would go far in giving us a better idea of how to help you.

However, as I've already explained, you can't write the TestAndSet() function in C, or in any high-level language for that matter, because it won't compile to an atomic action (that is, one which cannot be interrupted partway through - usually, a single CPU instruction, and specifically one which locks out interrupts as it executes; in modern processors, it must lock any other cores out from accessing the memory bus, as well). You must have an assembly language procedure for that, or at the very least a pair of assembly procedures that will block and unblock the process scheduler and interrupt handlers while the mutex code is in the critical section.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.