home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- The following is...
- Copyright (C) 1993 by Macquarie University
- Released without ANY warranty to the public domain.
- Written by Richard Larkin. rlarkin@zen.efs.mq.edu.au
-
- Thanks go to Mark Hahn for help with <sys/mman.h> functions.
-
- parallel.c - Code to achieve parallelism on multiprocessor architectures.
- ***************************************************************************/
-
- #include "parallel.h"
-
- #ifndef MSDOS
-
- /***************************************************************************
- Internally used structures.
- ***************************************************************************/
- typedef struct
- {
- void *P;
- long int Size;
- } PMAInfo;
-
-
- /***************************************************************************
- NumberProc number of processors available.
- NumberProcUsed number of processors in use after last split.
- ParentProcess true in the parent process.
- ***************************************************************************/
- static long int NumberProc = 1;
- static long int NumberProcUsed = 1;
- static int ParentProcess = TRUE;
-
-
- /***************************************************************************
- Parallel memory details.
- ***************************************************************************/
- static PMAInfo *PMA = NULL;
- static long int PMACnt = 0;
-
-
- /***************************************************************************
- ParallelProcessors tell parallel routines how many processors to assume.
- Pre : none.
- Post: Internal knowledge of number of processors set to maximum of N and 1.
- ***************************************************************************/
- void ParallelProcessors(long int N)
- {
- NumberProc = N < 1 ? 1 : N;
- }
-
-
- /***************************************************************************
- ParallelSplit split into useful number of processes and return
- interval of relevance to each process.
- Calls to ParallelSplit cannot be nested.
- Pre : Min, Max not NULL. NumberProcUsed == 1.
- Post: NumberProcUsed is number of active processes.
- [Min..Max) will be interval of Range to use for each process.
- ***************************************************************************/
- void ParallelSplit(long int Range, long int *Min, long int *Max)
- {
- NumberProcUsed = Range < NumberProc ? Range : NumberProc;
-
- /* Do we need to split? */
- if (NumberProcUsed > 1)
- {
- long int i;
-
- /* Split into seperate processes. */
- for (i = 0; i < NumberProcUsed - 1; i++)
- if (fork() == 0) break; /*ERROR fork() checks... */
-
- /* Parent is only process that makes it through entire loop. */
- ParentProcess = (i == NumberProcUsed-1);
-
- /* Select the range for this process. */
- *Min = i * (Range / NumberProcUsed);
- *Max = ParentProcess ? Range : (i+1) * (Range / NumberProcUsed);
- }
- else
- {
- /* Trivial range or number of processors. */
- *Min = 0; *Max = Range;
- }
- }
-
-
- /***************************************************************************
- ParallelRegroup children all return to their parent who waits for them.
- Pre : NumberProcUsed is number of active processes.
- Post: One parent process. NumberProcUsed = 1;
- ***************************************************************************/
- void ParallelRegroup(void)
- {
- /* Nontrivial regroup? */
- if (NumberProcUsed > 1)
- {
- /* Children GO HOME! */
- if (!ParentProcess) exit(0);
-
- /* Patient parent waits for children to arrive. */
- while (NumberProcUsed-- > 1) wait(NULL);
- }
- }
-
-
- /***************************************************************************
- ParallelCalloc allocated a piece of memory to be globally accessible
- throughout all processors.
- Pre : none.
- Post: Returns pointer to memory mapped parallel array file or
- in case of trivial processors returns normal Calloc result.
- Null returned on failure.
- ***************************************************************************/
- void *ParallelCalloc(size_t nitems, size_t size)
- {
- void *P;
-
- if (NumberProc > 1)
- {
- PMA = Realloc(PMA, (PMACnt+1) * sizeof(PMA[0]));
- PMA[PMACnt].Size = nitems * size;
-
- /* Set up the disk file to map into memory. */
- /* Map array and file together. */
- #ifdef SUN
- {
- int fd;
- if ((fd = open("/dev/zero", O_RDWR)) == -1) {/*ERROR*/};
-
- P = mmap(0, PMA[PMACnt].Size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- close(fd); /*ERROR check P != -1 */
- }
- #else
- P = mmap(0, PMA[PMACnt].Size, PROT_READ|PROT_WRITE,
- MAP_SHARED|MAP_ANONYMOUS, fd, 0);
- #endif
-
- madvise(P, PMA[PMACnt].Size, MADV_WILLNEED);
-
- /* Store so we can tidy up later. */
- PMA[PMACnt].P = P;
- PMACnt++;
- }
- else
- {
- P = calloc(nitems, size);
- }
-
- return P;
- }
-
- /***************************************************************************
- ParallelFree frees a piece of memory associated with a ParallelCalloc.
- Pre : *P is pointer return from ParallelCalloc().
- Post: Memory and possible file are freed.
- ***************************************************************************/
- void _ParallelFree(void *P)
- {
- if (NumberProc > 1 && P != NULL)
- {
- long int PMAi;
- int Last = TRUE;
-
- for (PMAi = 0; PMAi < PMACnt; PMAi++)
- {
- if (PMA[PMAi].P == P)
- {
- munmap((caddr_t) P, PMA[PMAi].Size);
- PMA[PMAi].P = NULL;
- }
-
- Last = Last && (PMA[PMAi].P == NULL);
- }
-
- if (Last) {free(PMA); PMACnt = 0;}
- }
- else
- free(P);
- }
-
- #endif
-
- /***************************************************************************
- End of parallel.c
- ***************************************************************************/
-