home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume41 / parallel / part01 / parallel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-19  |  6.0 KB  |  189 lines

  1. /***************************************************************************
  2.  The following is...
  3.       Copyright (C) 1993 by Macquarie University
  4.       Released without ANY warranty to the public domain.
  5.       Written by Richard Larkin. rlarkin@zen.efs.mq.edu.au
  6.  
  7.       Thanks go to Mark Hahn for help with <sys/mman.h> functions.
  8.  
  9.  parallel.c - Code to achieve parallelism on multiprocessor architectures.
  10.  ***************************************************************************/
  11.  
  12. #include "parallel.h"
  13.  
  14. #ifndef MSDOS
  15.  
  16. /***************************************************************************
  17.  Internally used structures.
  18.  ***************************************************************************/
  19. typedef struct
  20. {
  21.   void *P;
  22.   long int Size;
  23. } PMAInfo;
  24.  
  25.  
  26. /***************************************************************************
  27.  NumberProc number of processors available.
  28.  NumberProcUsed number of processors in use after last split.
  29.  ParentProcess true in the parent process.
  30.  ***************************************************************************/
  31. static long int NumberProc = 1;
  32. static long int NumberProcUsed = 1;
  33. static int ParentProcess = TRUE;
  34.  
  35.  
  36. /***************************************************************************
  37.  Parallel memory details.
  38.  ***************************************************************************/
  39. static PMAInfo *PMA = NULL;
  40. static long int PMACnt = 0;
  41.  
  42.  
  43. /***************************************************************************
  44.  ParallelProcessors tell parallel routines how many processors to assume.
  45.  Pre : none.
  46.  Post: Internal knowledge of number of processors set to maximum of N and 1.
  47.  ***************************************************************************/
  48. void ParallelProcessors(long int N)
  49. {
  50.   NumberProc = N < 1 ? 1 : N;
  51. }
  52.  
  53.  
  54. /***************************************************************************
  55.  ParallelSplit split into useful number of processes and return
  56.  interval of relevance to each process.
  57.  Calls to ParallelSplit cannot be nested.
  58.  Pre : Min, Max not NULL. NumberProcUsed == 1.
  59.  Post: NumberProcUsed is number of active processes.
  60.        [Min..Max) will be interval of Range to use for each process.
  61.  ***************************************************************************/
  62. void ParallelSplit(long int Range, long int *Min, long int *Max)
  63. {
  64.   NumberProcUsed = Range < NumberProc ? Range : NumberProc;
  65.  
  66.   /* Do we need to split?                                                  */
  67.   if (NumberProcUsed > 1)
  68.   {
  69.     long int i;
  70.  
  71.     /* Split into seperate processes.                                      */
  72.     for (i = 0; i < NumberProcUsed - 1; i++)
  73.       if (fork() == 0) break;                     /*ERROR fork() checks... */
  74.  
  75.     /* Parent is only process that makes it through entire loop.           */
  76.     ParentProcess = (i == NumberProcUsed-1);
  77.  
  78.     /* Select the range for this process.                                  */
  79.     *Min = i * (Range / NumberProcUsed);
  80.     *Max = ParentProcess ? Range : (i+1) * (Range / NumberProcUsed);
  81.   }
  82.   else
  83.   {
  84.     /* Trivial range or number of processors.                              */
  85.     *Min = 0; *Max = Range;
  86.   }
  87. }
  88.  
  89.  
  90. /***************************************************************************
  91.  ParallelRegroup children all return to their parent who waits for them.
  92.  Pre : NumberProcUsed is number of active processes.
  93.  Post: One parent process. NumberProcUsed = 1;
  94.  ***************************************************************************/
  95. void ParallelRegroup(void)
  96. {
  97.   /* Nontrivial regroup?                                                   */
  98.   if (NumberProcUsed > 1)
  99.   {
  100.     /* Children GO HOME!                                                   */
  101.     if (!ParentProcess) exit(0);
  102.  
  103.     /* Patient parent waits for children to arrive.                        */
  104.     while (NumberProcUsed-- > 1) wait(NULL);
  105.   }
  106. }
  107.  
  108.  
  109. /***************************************************************************
  110.  ParallelCalloc allocated a piece of memory to be globally accessible
  111.  throughout all processors.
  112.  Pre : none.
  113.  Post: Returns pointer to memory mapped parallel array file or
  114.        in case of trivial processors returns normal Calloc result.
  115.        Null returned on failure.
  116.  ***************************************************************************/
  117. void *ParallelCalloc(size_t nitems, size_t size)
  118. {
  119.   void *P;
  120.  
  121.   if (NumberProc > 1)
  122.   {
  123.     PMA = Realloc(PMA, (PMACnt+1) * sizeof(PMA[0]));
  124.     PMA[PMACnt].Size = nitems * size;
  125.  
  126.     /* Set up the disk file to map into memory.                            */
  127.     /* Map array and file together.                                        */
  128. #ifdef SUN
  129.     {
  130.       int fd;
  131.       if ((fd = open("/dev/zero", O_RDWR)) == -1) {/*ERROR*/};
  132.  
  133.       P = mmap(0, PMA[PMACnt].Size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  134.       close(fd);      /*ERROR check P != -1 */
  135.     }
  136. #else
  137.     P = mmap(0, PMA[PMACnt].Size, PROT_READ|PROT_WRITE, 
  138.                 MAP_SHARED|MAP_ANONYMOUS, fd, 0);
  139. #endif
  140.  
  141.     madvise(P, PMA[PMACnt].Size, MADV_WILLNEED);
  142.  
  143.     /* Store so we can tidy up later.                                      */
  144.     PMA[PMACnt].P = P;
  145.     PMACnt++;
  146.   }
  147.   else
  148.   {
  149.     P = calloc(nitems, size);
  150.   }
  151.  
  152.   return P;
  153. }
  154.  
  155. /***************************************************************************
  156.  ParallelFree frees a piece of memory associated with a ParallelCalloc.
  157.  Pre : *P is pointer return from ParallelCalloc().
  158.  Post: Memory and possible file are freed.
  159.  ***************************************************************************/
  160. void _ParallelFree(void *P)
  161. {
  162.   if (NumberProc > 1 && P != NULL)
  163.   {
  164.     long int PMAi;
  165.     int Last = TRUE;
  166.  
  167.     for (PMAi = 0; PMAi < PMACnt; PMAi++)
  168.     {
  169.       if (PMA[PMAi].P == P)
  170.       {
  171.         munmap((caddr_t) P, PMA[PMAi].Size);
  172.         PMA[PMAi].P = NULL;
  173.       }
  174.  
  175.       Last = Last && (PMA[PMAi].P == NULL);
  176.     }
  177.  
  178.     if (Last) {free(PMA); PMACnt = 0;}
  179.   }
  180.   else
  181.     free(P);
  182. }
  183.  
  184. #endif 
  185.  
  186. /***************************************************************************
  187.  End of parallel.c
  188.  ***************************************************************************/
  189.