LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - shmqueue.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 42 43 97.7 %
Date: 2019-06-18 07:06:57 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * shmqueue.c
       4             :  *    shared memory linked lists
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/storage/ipc/shmqueue.c
      12             :  *
      13             :  * NOTES
      14             :  *
      15             :  * Package for managing doubly-linked lists in shared memory.
      16             :  * The only tricky thing is that SHM_QUEUE will usually be a field
      17             :  * in a larger record.  SHMQueueNext has to return a pointer
      18             :  * to the record itself instead of a pointer to the SHMQueue field
      19             :  * of the record.  It takes an extra parameter and does some extra
      20             :  * pointer arithmetic to do this correctly.
      21             :  *
      22             :  * NOTE: These are set up so they can be turned into macros some day.
      23             :  *
      24             :  *-------------------------------------------------------------------------
      25             :  */
      26             : #include "postgres.h"
      27             : 
      28             : #include "storage/shmem.h"
      29             : 
      30             : 
      31             : /*
      32             :  * ShmemQueueInit -- make the head of a new queue point
      33             :  *      to itself
      34             :  */
      35             : void
      36     7713938 : SHMQueueInit(SHM_QUEUE *queue)
      37             : {
      38             :     Assert(ShmemAddrIsValid(queue));
      39     7713938 :     queue->prev = queue->next = queue;
      40     7713938 : }
      41             : 
      42             : /*
      43             :  * SHMQueueIsDetached -- true if element is not currently
      44             :  *      in a queue.
      45             :  */
      46             : bool
      47        9790 : SHMQueueIsDetached(const SHM_QUEUE *queue)
      48             : {
      49             :     Assert(ShmemAddrIsValid(queue));
      50        9790 :     return (queue->prev == NULL);
      51             : }
      52             : 
      53             : /*
      54             :  * SHMQueueElemInit -- clear an element's links
      55             :  */
      56             : void
      57       24366 : SHMQueueElemInit(SHM_QUEUE *queue)
      58             : {
      59             :     Assert(ShmemAddrIsValid(queue));
      60       24366 :     queue->prev = queue->next = NULL;
      61       24366 : }
      62             : 
      63             : /*
      64             :  * SHMQueueDelete -- remove an element from the queue and
      65             :  *      close the links
      66             :  */
      67             : void
      68     4458558 : SHMQueueDelete(SHM_QUEUE *queue)
      69             : {
      70     4458558 :     SHM_QUEUE  *nextElem = queue->next;
      71     4458558 :     SHM_QUEUE  *prevElem = queue->prev;
      72             : 
      73             :     Assert(ShmemAddrIsValid(queue));
      74             :     Assert(ShmemAddrIsValid(nextElem));
      75             :     Assert(ShmemAddrIsValid(prevElem));
      76             : 
      77     4458558 :     prevElem->next = queue->next;
      78     4458558 :     nextElem->prev = queue->prev;
      79             : 
      80     4458558 :     queue->prev = queue->next = NULL;
      81     4458558 : }
      82             : 
      83             : /*
      84             :  * SHMQueueInsertBefore -- put elem in queue before the given queue
      85             :  *      element.  Inserting "before" the queue head puts the elem
      86             :  *      at the tail of the queue.
      87             :  */
      88             : void
      89    16224798 : SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
      90             : {
      91    16224798 :     SHM_QUEUE  *prevPtr = queue->prev;
      92             : 
      93             :     Assert(ShmemAddrIsValid(queue));
      94             :     Assert(ShmemAddrIsValid(elem));
      95             : 
      96    16224798 :     elem->next = prevPtr->next;
      97    16224798 :     elem->prev = queue->prev;
      98    16224798 :     queue->prev = elem;
      99    16224798 :     prevPtr->next = elem;
     100    16224798 : }
     101             : 
     102             : /*
     103             :  * SHMQueueInsertAfter -- put elem in queue after the given queue
     104             :  *      element.  Inserting "after" the queue head puts the elem
     105             :  *      at the head of the queue.
     106             :  */
     107             : void
     108          76 : SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem)
     109             : {
     110          76 :     SHM_QUEUE  *nextPtr = queue->next;
     111             : 
     112             :     Assert(ShmemAddrIsValid(queue));
     113             :     Assert(ShmemAddrIsValid(elem));
     114             : 
     115          76 :     elem->prev = nextPtr->prev;
     116          76 :     elem->next = queue->next;
     117          76 :     queue->next = elem;
     118          76 :     nextPtr->prev = elem;
     119          76 : }
     120             : 
     121             : /*--------------------
     122             :  * SHMQueueNext -- Get the next element from a queue
     123             :  *
     124             :  * To start the iteration, pass the queue head as both queue and curElem.
     125             :  * Returns NULL if no more elements.
     126             :  *
     127             :  * Next element is at curElem->next.  If SHMQueue is part of
     128             :  * a larger structure, we want to return a pointer to the
     129             :  * whole structure rather than a pointer to its SHMQueue field.
     130             :  * For example,
     131             :  * struct {
     132             :  *      int             stuff;
     133             :  *      SHMQueue        elem;
     134             :  * } ELEMType;
     135             :  * When this element is in a queue, prevElem->next points at struct.elem.
     136             :  * We subtract linkOffset to get the correct start address of the structure.
     137             :  *
     138             :  * calls to SHMQueueNext should take these parameters:
     139             :  *   &(queueHead), &(queueHead), offsetof(ELEMType, elem)
     140             :  * or
     141             :  *   &(queueHead), &(curElem->elem), offsetof(ELEMType, elem)
     142             :  *--------------------
     143             :  */
     144             : Pointer
     145    16437584 : SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
     146             : {
     147    16437584 :     SHM_QUEUE  *elemPtr = curElem->next;
     148             : 
     149             :     Assert(ShmemAddrIsValid(curElem));
     150             : 
     151    16437584 :     if (elemPtr == queue)       /* back to the queue head? */
     152    14793752 :         return NULL;
     153             : 
     154     1643832 :     return (Pointer) (((char *) elemPtr) - linkOffset);
     155             : }
     156             : 
     157             : /*--------------------
     158             :  * SHMQueuePrev -- Get the previous element from a queue
     159             :  *
     160             :  * Same as SHMQueueNext, just starting at tail and moving towards head.
     161             :  * All other comments and usage applies.
     162             :  */
     163             : Pointer
     164          76 : SHMQueuePrev(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
     165             : {
     166          76 :     SHM_QUEUE  *elemPtr = curElem->prev;
     167             : 
     168             :     Assert(ShmemAddrIsValid(curElem));
     169             : 
     170          76 :     if (elemPtr == queue)       /* back to the queue head? */
     171          76 :         return NULL;
     172             : 
     173           0 :     return (Pointer) (((char *) elemPtr) - linkOffset);
     174             : }
     175             : 
     176             : /*
     177             :  * SHMQueueEmpty -- true if queue head is only element, false otherwise
     178             :  */
     179             : bool
     180       13190 : SHMQueueEmpty(const SHM_QUEUE *queue)
     181             : {
     182             :     Assert(ShmemAddrIsValid(queue));
     183             : 
     184       13190 :     if (queue->prev == queue)
     185             :     {
     186             :         Assert(queue->next == queue);
     187        9098 :         return true;
     188             :     }
     189        4092 :     return false;
     190             : }

Generated by: LCOV version 1.13