File: BI_GetBuff.c

package info (click to toggle)
blacs-mpi 1.1-28.2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 2,320 kB
  • ctags: 2,031
  • sloc: fortran: 14,968; ansic: 12,353; makefile: 531; sh: 1
file content (76 lines) | stat: -rw-r--r-- 3,372 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "Bdef.h"
/***************************************************************************
 *  The mpi implements globally blocking sends.  I.e., a send blocks until *
 *  the dest. node issues a recv.  The BLACS assume locally-blocking sends.*
 *  Therefore, the BLACS must fake locally-blocking sends.  To do this     *
 *  requires an indeterminate number of buffers and the use of             *
 *  non-blocking sends.  However, it is very important that even though I  *
 *  provide a dynamic number of buffers, that getting these buffers does   *
 *  not take too long in the critical part of a send operation.            *
 *  Therefore, the buffer management is broken into two routines.          *
 *									   *
 *  Inside the BLACS there are two states a buffer may be in.  If the buff *
 *  is currently being used (for instance, an asynchronous send is coming  *
 *  from it), it is classified as an ACTIVE buffer, and is on the active   *
 *  buffer queue.  Otherwise, a buffer is READY: it is not being used      *
 *  and is available for the next buffer operation.                        *
 *  In order to avoid buffer proliferation, only one ready buffer is kept, *
 *  and as active buffers become inactive they either become the ready     *
 *  buffer, or are freed.						   *
 *  									   *
 *  The first routine, BI_GetBuff, checks if the ready buffer is big enough   *
 *  to fulfill the buffer request.  If not, the present ready buffer is    *
 *  is freed, and a new buffer of the required length is allocated.  If    *
 *  the buffer is of sufficent size already, no action is taken.           *
 *  This routine is purposely very short, as it is called at the beginning *
 *  of each broadcast/send operation.  All participating nodes             *
 *  are waiting on the source node, so this routine must be very cheap.	   *
 *									   *
 *  The second routine, BI_UpdateBuffs, moves the ready buffer to the active  *
 *  buffer queue (if needed).  It also checks the entire active buffer     *
 *  queue to see if any have finished their operations.  If so, they are   *
 *  are either moved to the ready buff, or freed.  This routine is called  *
 *  AFTER the send/broadcast has been started, and thus I am free to make  *
 *  it a little more complex.						   *
 ***************************************************************************/

BLACBUFF *BI_GetBuff(int length)
{
   void BI_EmergencyBuff(int length);

   char *cptr;
   int i, j;
   extern int BI_Np;
   extern BLACBUFF *BI_ReadyB;

/*
 * If ready buffer already exists, and is big enough, return it.  Otherwise,
 * free the buffer (if it exists) and get one of correct size
 */
   if (BI_ReadyB)
   {
      if (BI_ReadyB->Len >= length) return(BI_ReadyB);
      else free(BI_ReadyB);
   }
/*
 * Make sure all buffers aligned correctly
 */
   j = sizeof(BLACBUFF);
   if (j % sizeof(BI_MPI_Request))
      j += sizeof(BI_MPI_Request) - j % sizeof(BI_MPI_Request);
   i = j + BI_Np*sizeof(BI_MPI_Request);
   if (i % BUFFALIGN) i += BUFFALIGN - i % BUFFALIGN;
   cptr = malloc(i + length);
   BI_ReadyB = (BLACBUFF *) cptr;

   if (BI_ReadyB != NULL)
   {
      BI_ReadyB->nAops = 0;
      BI_ReadyB->Aops = (BI_MPI_Request *) &cptr[j];
      BI_ReadyB->Buff = &cptr[i];
      BI_ReadyB->Len = length;
   }
   else BI_EmergencyBuff(length);

   return(BI_ReadyB);
}