home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_shmem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  5.2 KB  |  193 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    ex_shmem.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    code for a specialized memory allocator to manage the shared memory
  7.  *    for the parallel executor
  8.  *
  9.  *   INTERFACE ROUTINES
  10.  *    ExecSMInit - initializes the shared mem meta-data
  11.  *    ExecGetSMSegment - allocates a segment of shared memory
  12.  *    ExecSMSegmentFree - frees a segment of shared memory
  13.  *    ExecSMSegmentFreeUnused    - frees unused memory in a segment
  14.  *
  15.  *   NOTES
  16.  *    the key consideration is to avoid allocation overhead.  two
  17.  *    important reasons lead to this special memory allocator:
  18.  *    1. only the master backend allocates the shared memory;
  19.  *    2. the shared memory is used for passing querydescs and reldescs,
  20.  *       which consists of small nodes.
  21.  *    basically, the pattern of memory allocation we are dealing with is
  22.  *    that the master issues a bunch of small requests then frees them
  23.  *    at the same time.  so here the idea is to pack these
  24.  *    small chunks of allocated memory into one segment.
  25.  *
  26.  *    memory is managed as a a linked list of variable-size segments,
  27.  *    efforts has been made to merge consecutive segments into
  28.  *    larger segments, initially the entire executor shared memory is
  29.  *    one segment.
  30.  *
  31.  *    the functions here only deal with segments, allocations inside
  32.  *    a segment is handled by specialied functions ProcGroupSMBeginAlloc(),
  33.  *    ProcGroupSMEndAlloc() and ProcGroupSMAlloc() in tcop/slaves.c.
  34.  *
  35.  *   IDENTIFICATION
  36.  *    $Header: /private/postgres/src/executor/RCS/ex_shmem.c,v 1.4 1991/11/14 11:00:54 glass Exp $
  37.  * ----------------------------------------------------------------
  38.  */
  39.  
  40. #include "tmp/align.h"
  41. #include "utils/log.h"
  42. #include "executor/execshmem.h"
  43.  
  44.  RcsId("$Header: /private/postgres/src/executor/RCS/ex_shmem.c,v 1.4 1991/11/14 11:00:54 glass Exp $");
  45.  
  46.  
  47.  
  48.  
  49. static MemoryHeader FreeSMQueue;  /* queue of free SM */
  50. extern char *ExecutorSharedMemory;
  51. extern int ExecutorSharedMemorySize;
  52.  
  53. /* -------------------------------
  54.  *    ExecSMReserve
  55.  *
  56.  *    reserve a certain number of bytes in the executor shared memory
  57.  *    for the global shared variables
  58.  * -------------------------------
  59.  */
  60. char *
  61. ExecSMReserve(size)
  62. int size;
  63. {
  64.     char *p;
  65.  
  66.     p = ExecutorSharedMemory;
  67.     ExecutorSharedMemory = (char*)LONGALIGN(ExecutorSharedMemory + size);
  68.     ExecutorSharedMemorySize -= (ExecutorSharedMemory - p);
  69.     return p;
  70. }
  71.  
  72. /* --------------------------------
  73.  *    ExecSMInit
  74.  *
  75.  *    This function initializes executor shared memory.
  76.  *    Initially, the whole thing is a segment.
  77.  * --------------------------------
  78.  */
  79. void
  80. ExecSMInit()
  81. {
  82.     FreeSMQueue = (MemoryHeader)ExecutorSharedMemory;
  83.     /* -------------------
  84.      * assume sizeof(MemoryHeaderData) is multiple of sizeof(long),
  85.      * too lazy to put LONGALIGN() all over the places,
  86.      * not good for portability, eventually will put LONGALIGN() in.
  87.      * -------------------
  88.      */
  89.     FreeSMQueue->beginaddr = ExecutorSharedMemory + sizeof(MemoryHeaderData);
  90.     FreeSMQueue->size = ExecutorSharedMemorySize - sizeof(MemoryHeaderData);
  91.     FreeSMQueue->next = NULL;
  92. }
  93.  
  94. /* -------------------------------
  95.  *    ExecGetSMSegment
  96.  *
  97.  *    get a free memory segment from the free memory queue
  98.  * -------------------------------
  99.  */
  100. MemoryHeader
  101. ExecGetSMSegment()
  102. {
  103.     MemoryHeader p;
  104.  
  105.     if (FreeSMQueue == NULL)
  106.     elog(WARN, "out of shared memory segments for parallel executor.");
  107.     p = FreeSMQueue;
  108.     FreeSMQueue = FreeSMQueue->next;
  109.  
  110.     return p;
  111. }
  112.  
  113. /* ---------------------------------
  114.  *    mergeSMSegment
  115.  *
  116.  *    try to merge two segments, returns true if successful, false otherwise
  117.  * ---------------------------------
  118.  */
  119. static bool
  120. mergeSMSegment(lowSeg, highSeg)
  121. MemoryHeader lowSeg, highSeg;
  122. {
  123.     if (lowSeg == NULL || highSeg == NULL)
  124.     return false;
  125.     if ((char*)LONGALIGN(lowSeg->beginaddr + lowSeg->size) == (char*)highSeg) {
  126.     lowSeg->size = highSeg->beginaddr + highSeg->size - lowSeg->beginaddr;
  127.     lowSeg->next = highSeg->next;
  128.     return true;
  129.       }
  130.     return false;
  131. }
  132.  
  133. /* ----------------------------
  134.  *    ExecSMSegmentFree
  135.  *
  136.  *    frees a memory segment
  137.  *    insert the segment into the free queue in ascending order of
  138.  *    the begining address
  139.  *    merge with neighbors if possible
  140.  * -----------------------------
  141.  */
  142. void
  143. ExecSMSegmentFree(mp)
  144. MemoryHeader mp;
  145. {
  146.     MemoryHeader prev, cur;
  147.     prev = NULL;
  148.     for (cur=FreeSMQueue; cur!=NULL; cur=cur->next) {
  149.     if (cur->beginaddr > mp->beginaddr)
  150.         break;
  151.     prev = cur;
  152.       }
  153.     if (prev == NULL) {
  154.     FreeSMQueue = mp;
  155.     if (!mergeSMSegment(mp, cur))
  156.         mp->next = cur;
  157.       }
  158.     else {
  159.     mp->next = cur;
  160.     if (mergeSMSegment(prev, mp)) {
  161.         mergeSMSegment(prev, cur);
  162.       }
  163.     else {
  164.         prev->next = mp;
  165.         mergeSMSegment(mp, cur);
  166.       }
  167.       }
  168. }
  169.  
  170. #define MINFREESIZE    10*sizeof(MemoryHeaderData)
  171.  
  172. /* ---------------------------
  173.  *    ExecSMSegmentFreeUnused
  174.  *
  175.  *    frees unused memory in a segment
  176.  * ---------------------------
  177.  */
  178. void
  179. ExecSMSegmentFreeUnused(mp, usedsize)
  180. MemoryHeader mp;
  181. int usedsize;
  182. {
  183.     MemoryHeader newmp;
  184.  
  185.     if (mp->size - usedsize < MINFREESIZE)
  186.     return;
  187.     newmp = (MemoryHeader)LONGALIGN(mp->beginaddr + usedsize);
  188.     newmp->beginaddr = (char*)newmp + sizeof(MemoryHeaderData);
  189.     newmp->size = mp->beginaddr + mp->size - newmp->beginaddr;
  190.     mp->size = usedsize;
  191.     ExecSMSegmentFree(newmp);
  192. }
  193.