/*************************PARALLEL PROGRAMMING **/ /***********************************************************/ /** This contains the C codes for Fork, Join, Spinlocks **/ /** and all shared memory routines such as Shareint, Sharereal **/ /** Sharerealarray, Sharebarrier, Sharelist etc. You can add **/ /** additional share files if you need. **/ /**************************************************************/ /** NECESSARY SYSTEM FILES **/ /**************************************************************/ #include #include #include #include #include #include #include /***************************************************/ /** FORK FOR PROGRAMS **/ /***************************************************/ int process_fork (int nproc) { int j; for (j = 1; j <= (nproc) - 1; j++) if (fork () == 0) return (j); return (0); } /***************************************************/ /** JOIN FOR PROGRAMS **/ /***************************************************/ void process_join (int nproc, int id) /* when a child calls this, it is terminated. when the parent calls this it waits for all the children to be terminated */ { int i; if (id == 0) for (i = 1; i <= nproc - 1; i++) wait (0); /* parent waits */ else exit (0); /* child leaves */ } /*************************************************************/ /** SPINLOCKS - IMPLEMENTED WITH SEMAPHORES FOR **/ /*************************************************************/ /*************************************************************/ /********* INITIALIZATION OF SPINLOCKS **********/ /*************************************************************/ /* MODIFICATION */ /* spin_lock_init() now requires a pointer to an integer as the */ /* first parameter. This allows the function to return */ /* the system generated semaphore ID to the calling function. */ /* The returned ID can then be passed to clean_up_sem() to allow */ /* the system to remove the semaphore. Also since IPC_PRIVATE is */ /* passed as the key, the permission flags passed to semget only */ /* need to be 0666 not 0666|IPC_CREAT. When the flag is IPC_PRIVATE, */ /* the system will always generate a new semaphore unless there are no */ /* more to give out -- Andres Martinez */ void spin_lock_init (int *lock, int condition) { /* union semun control; */ /* This particular union/struct was defined in SunOS but not in Solaris. User-defined is required. -Henry Liao */ union semun { int val; struct semid_ds *buf; ushort *array; } control; if ((*lock = semget (IPC_PRIVATE, 1, 0666)) < 0) perror ("semget"); if (condition == 0) control.val = 1; else control.val = 0; if (semctl (*lock, 0, SETVAL, control) < 0) perror ("semctl"); } /**************************************************************/ /********* LOCKING SPINLOCKS *********/ /**************************************************************/ void spin_lock (int lock) { struct { short num; short op; short flag; } operations; operations.num = 0; operations.op = -1; operations.flag = 0; /* typecast the struct to elimiate warning -Henry Liao */ semop (lock, (struct sembuf *) &operations, 1); } /***************************************************************/ /******* UNLOCKING SPINLOCKS *************/ /***************************************************************/ void spin_unlock (int lock) { struct { short num; short op; short flag; } operations; operations.num = 0; operations.op = 1; operations.flag = 0; semop (lock, (struct sembuf *) &operations, 1); } /******************************************************************/ /********* SHARED MEMORY FOR INT, REAL, ARRAY, LIST & BARRIER ****/ /******************************************************************/ /* MODIFICATION */ /* All shared memory functions now require a pointer to an integer */ /* for their second parameter. This allows the function to return */ /* the system generated shared memory ID to the calling function. */ /* The returned ID can then be passed to clean_up_shared() to allow */ /* the system to remove the shared memory segment. Also since */ /* IPC_PRIVATE is passed as the key, the permission flags */ /* passed to shmget only need to be 0666 not 0666|IPC_CREAT. */ /* When the flag is IPC_PRIVATE, the system will always generate a */ /* new shared memory segment unless there are no more to give out. */ /* -- Andres Martinez */ /*****************************************************************/ /********* SHARED MEMORY FOR REAL-ARRAY ********/ /*****************************************************************/ int *sharerealarray (int size, int *shmid) { *shmid = shmget (IPC_PRIVATE, size, 0666); return ((int *) shmat (*shmid, 0, 0)); } /*****************************************************************/ /********** SHARED MEMORY FOR INTEGER ************/ /*****************************************************************/ int *shareint (int size, int *shmid) { *shmid = shmget (IPC_PRIVATE, size, 0666); return ((int *) shmat (*shmid, 0, 0)); } /*****************************************************************/ /********** SHARED MEMORY FOR REAL ************/ /*****************************************************************/ int *sharereal (int size, int *shmid) { *shmid = shmget (IPC_PRIVATE, size, 0666); return ((int *) shmat (*shmid, 0, 0)); } /******************************************************************/ /********** SHARED MEMORY FOR BARRIER *************/ /******************************************************************/ int *sharebarrier (int size, int *shmid) { *shmid = shmget (IPC_PRIVATE, size, 0666); return ((int *) shmat (*shmid, 0, 0)); } /********************************************************************/ /** SHARED MEMORY FOR ABSTRACT TYPE LIST - MUST BE PREDEFINED ***/ /** IN THE PROGRAM ***/ /********************************************************************/ int *sharelist (int size, int *shmid) { *shmid = shmget (IPC_PRIVATE, size, 0666); return ((int *) shmat (*shmid, 0, 0)); } /*********************************************************************/ /** CLEAN UP OF SHARED MEMORY. THIS PROCEDURE RELEASES SHARED */ /** REFERENCED BY IDSHAREMEM. USER MUST PASS IDSHAREMEM */ /*********************************************************************/ void clean_up_shared (int IdShareMem) { struct shmid_ds *buf; shmctl (IdShareMem, IPC_RMID, buf); } /*********************************************************************/ /** CLEAN UP SEMAPHORE. THIS FUNCTION RELEASES THE SEMAPHORE */ /** REFERENCED BY IdSem. USER MUST PASS IdSem. */ /*********************************************************************/ void clean_up_sem (int IdSem) { semctl (IdSem, 0, IPC_RMID); }