LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - shmqueue.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 42 57 73.7 %
Date: 2017-09-29 13:40:31 Functions: 7 9 77.8 %
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-2017, 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      182241 : SHMQueueInit(SHM_QUEUE *queue)
      37             : {
      38      182241 :     Assert(ShmemAddrIsValid(queue));
      39      182241 :     queue->prev = queue->next = queue;
      40      182241 : }
      41             : 
      42             : /*
      43             :  * SHMQueueIsDetached -- TRUE if element is not currently
      44             :  *      in a queue.
      45             :  */
      46             : bool
      47         362 : SHMQueueIsDetached(const SHM_QUEUE *queue)
      48             : {
      49         362 :     Assert(ShmemAddrIsValid(queue));
      50         362 :     return (queue->prev == NULL);
      51             : }
      52             : 
      53             : /*
      54             :  * SHMQueueElemInit -- clear an element's links
      55             :  */
      56             : void
      57         698 : SHMQueueElemInit(SHM_QUEUE *queue)
      58             : {
      59         698 :     Assert(ShmemAddrIsValid(queue));
      60         698 :     queue->prev = queue->next = NULL;
      61         698 : }
      62             : 
      63             : /*
      64             :  * SHMQueueDelete -- remove an element from the queue and
      65             :  *      close the links
      66             :  */
      67             : void
      68      174654 : SHMQueueDelete(SHM_QUEUE *queue)
      69             : {
      70      174654 :     SHM_QUEUE  *nextElem = queue->next;
      71      174654 :     SHM_QUEUE  *prevElem = queue->prev;
      72             : 
      73      174654 :     Assert(ShmemAddrIsValid(queue));
      74      174654 :     Assert(ShmemAddrIsValid(nextElem));
      75      174654 :     Assert(ShmemAddrIsValid(prevElem));
      76             : 
      77      174654 :     prevElem->next = queue->next;
      78      174654 :     nextElem->prev = queue->prev;
      79             : 
      80      174654 :     queue->prev = queue->next = NULL;
      81      174654 : }
      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      208382 : SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
      90             : {
      91      208382 :     SHM_QUEUE  *prevPtr = queue->prev;
      92             : 
      93      208382 :     Assert(ShmemAddrIsValid(queue));
      94      208382 :     Assert(ShmemAddrIsValid(elem));
      95             : 
      96      208382 :     elem->next = prevPtr->next;
      97      208382 :     elem->prev = queue->prev;
      98      208382 :     queue->prev = elem;
      99      208382 :     prevPtr->next = elem;
     100      208382 : }
     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           0 : SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem)
     109             : {
     110           0 :     SHM_QUEUE  *nextPtr = queue->next;
     111             : 
     112           0 :     Assert(ShmemAddrIsValid(queue));
     113           0 :     Assert(ShmemAddrIsValid(elem));
     114             : 
     115           0 :     elem->prev = nextPtr->prev;
     116           0 :     elem->next = queue->next;
     117           0 :     queue->next = elem;
     118           0 :     nextPtr->prev = elem;
     119           0 : }
     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      907534 : SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
     146             : {
     147      907534 :     SHM_QUEUE  *elemPtr = curElem->next;
     148             : 
     149      907534 :     Assert(ShmemAddrIsValid(curElem));
     150             : 
     151      907534 :     if (elemPtr == queue)       /* back to the queue head? */
     152      843032 :         return NULL;
     153             : 
     154       64502 :     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           0 : SHMQueuePrev(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
     165             : {
     166           0 :     SHM_QUEUE  *elemPtr = curElem->prev;
     167             : 
     168           0 :     Assert(ShmemAddrIsValid(curElem));
     169             : 
     170           0 :     if (elemPtr == queue)       /* back to the queue head? */
     171           0 :         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       97250 : SHMQueueEmpty(const SHM_QUEUE *queue)
     181             : {
     182       97250 :     Assert(ShmemAddrIsValid(queue));
     183             : 
     184       97250 :     if (queue->prev == queue)
     185             :     {
     186       97247 :         Assert(queue->next == queue);
     187       97247 :         return TRUE;
     188             :     }
     189           3 :     return FALSE;
     190             : }

Generated by: LCOV version 1.11