Veil
veil_shmem.c File Reference

Functions for dealing with veil shared memory. More...

#include "postgres.h"
#include "utils/hsearch.h"
#include "storage/pg_shmem.h"
#include "storage/shmem.h"
#include "storage/lwlock.h"
#include "storage/procarray.h"
#include "access/xact.h"
#include "access/transam.h"
#include "miscadmin.h"
#include "veil_version.h"
#include "veil_shmem.h"
#include "veil_funcs.h"

Go to the source code of this file.

Macros

#define OTHER_CONTEXT(x)   (x ? 0: 1)
 Return the index of the other context from the one supplied. More...
 

Functions

static LWLock * NextLWLock ()
 Return the next LWLock from our tranche. More...
 
void _PG_init ()
 Veil's startup function. More...
 
static HTAB * create_shared_hash (const char *hashname)
 Create/attach to the shared hash identified by hashname. More...
 
static HTAB * get_hash0 ()
 Return reference to the HTAB for the shared hash associated with context 0. More...
 
static HTAB * get_hash1 ()
 Return reference to the HTAB for the shared hash associated with context 1. More...
 
static MemContextget_shmem_context (char *name, size_t size, bool *p_found)
 Allocate or attach to, a new chunk of shared memory for a named memory context. More...
 
static void shmalloc_init (void)
 Attach to, creating and initialising as necessary, the shared memory control structure. More...
 
static int get_cur_context_id ()
 Return the id (index) of the current context for this session. More...
 
static MemContextget_cur_context ()
 Return pointer to shared memory allocated for the current context. More...
 
static void * do_vl_shmalloc (MemContext *context, size_t size)
 Dynamically allocate a piece of shared memory from the current context, doing no locking. More...
 
void * vl_shmalloc (size_t size)
 Dynamically allocate a piece of shared memory from the current context. More...
 
void vl_free (void *mem)
 Free a piece of shared memory within the current context. More...
 
HTAB * vl_get_shared_hash ()
 Return the shared hash for the current context. More...
 
static void clear_hash (HTAB *hash)
 Reset one of the shared hashes. More...
 
bool vl_prepare_context_switch ()
 Prepare for a switch to the alternate context. More...
 
bool vl_complete_context_switch ()
 Complete the context switch started by vl_prepare_context_switch(). More...
 
void vl_force_context_switch ()
 In desparation, if we are unable to complete a context switch, we should use this function.
 

Variables

static ShmemCtlshared_meminfo = NULL
 shared_meminfo provides access to the ShmemCtl structure allocated in context 0.
 
static bool prepared_for_switch = false
 Whether the current backend is in the process of switching contexts. More...
 
static LWLockId VeilLWLock = 0
 The LWLock that Veil will use for managing concurrent access to shared memory. More...
 
static LWLockId InitialLWLock = 0
 The LWLock to be used while initially setting up shared memory and allocating a veil database-specific LWLock. More...
 
static MemContextlwlock_context
 The MemContext that we use to manage our tranche of LWLocks.
 
static char * TRANCHE_NAME = "veil"
 Name of tranche of LWLocks used by veil.
 

Detailed Description

Functions for dealing with veil shared memory.

Author: Marc Munro
Copyright (c) 2005 - 2018 Marc Munro
License: BSD

This provides dynamic memory allocation, like malloc, from chunks of shared memory allocated from the Postgres shared memory pool. In order to be able to reset and reload shared memory structures while other backends continue to use the existing structures, a shared memory reset creates a new context, or switches to an existing one that is no longer in use. No more than two separate contexts will be created.

Each context of veil shared memory is associated with a shared hash, which is used to store veil's shared variables. A specially named variable, VEIL_SHMEMCTL appears only in context0 and contains a reference to chunk0, and the ShmemCtl structure. From this structure we can identify the current context, the initial chunks for each active context, and whether a context switch is in progress.

A context switch takes place in 3 steps:

  • preparation, in which we determine if a context switch is allowed, initialise the new context and record the fact that we are in the process of switching. All subsequent operations in the current backend will work in the new context, while other backends will continue to use the original context
  • initialisation of the new context, variables, etc. This is done by the user-space function veil_init().
  • switchover, when all other processes gain access to the newly initialised context. They may continue to use the previous context for the duration of their current transactions.

To access shared variable "x" in a new session, the following steps are taken:

  • We access the hash "VEIL_SHARED1_nnn" (where nnn is the oid of our database). This gives us a reference to the ShmemCtl structure. We record hash0 and shared_meminfo on the way.
  • We access ShemCtl to identify the current hash and current context.
  • We look up variable "x" in the current hash, and if we have to allocate space for it, allocate it from the current context.

Note that We use a dynamically allocated LWLock, VeilLWLock to protect our shared control structures.

Definition in file veil_shmem.c.

Macro Definition Documentation

◆ OTHER_CONTEXT

#define OTHER_CONTEXT (   x)    (x ? 0: 1)

Return the index of the other context from the one supplied.

Parameters
xthe context for which we want the other one.
Returns
the opposite context to that of x.

Definition at line 101 of file veil_shmem.c.

Referenced by get_cur_context_id(), vl_complete_context_switch(), vl_force_context_switch(), and vl_prepare_context_switch().

Function Documentation

◆ NextLWLock()

static LWLock* NextLWLock ( )
static

Return the next LWLock from our tranche.

Note that locking is the responsibility of the caller.

Definition at line 118 of file veil_shmem.c.

References MemContext::lwlock_idx, and MemContext::lwlock_tranche.

Referenced by shmalloc_init().

◆ _PG_init()

void _PG_init ( void  )

Veil's startup function.

This should be run when the Veil shared library is loaded by postgres.

Definition at line 141 of file veil_shmem.c.

References InitialLWLock, TRANCHE_NAME, veil_config_init(), veil_dbs_in_cluster(), veil_shmem_context_size(), and VeilLWLock.

◆ create_shared_hash()

static HTAB* create_shared_hash ( const char *  hashname)
static

Create/attach to the shared hash identified by hashname.

Return a pointer to an HTAB that references the shared hash. All locking is handled by the caller.

Parameters
hashname
Returns
Pointer to HTAB referencing the shared hash.

Definition at line 170 of file veil_shmem.c.

References HASH_KEYLEN, veil_shared_hash_elems(), and vl_malloc().

Referenced by get_hash0(), and get_hash1().

◆ get_hash0()

static HTAB* get_hash0 ( )
static

Return reference to the HTAB for the shared hash associated with context 0.

Returns
Pointer to HTAB referencing shared hash for context 0.

Definition at line 199 of file veil_shmem.c.

References create_shared_hash().

Referenced by vl_force_context_switch(), vl_get_shared_hash(), and vl_prepare_context_switch().

◆ get_hash1()

static HTAB* get_hash1 ( )
static

Return reference to the HTAB for the shared hash associated with context 1.

Returns
Pointer to HTAB referencing shared hash for context 1.

Definition at line 216 of file veil_shmem.c.

References create_shared_hash().

Referenced by vl_force_context_switch(), vl_get_shared_hash(), and vl_prepare_context_switch().

◆ get_shmem_context()

static MemContext* get_shmem_context ( char *  name,
size_t  size,
bool *  p_found 
)
static

Allocate or attach to, a new chunk of shared memory for a named memory context.

Parameters
nameThe name
sizeThe size of the shared memory chunk to be allocated.
p_foundPointer to boolean that will identify whether this chunk has already been initialised.
Returns
Pointer to chunk of shared memory.

Definition at line 240 of file veil_shmem.c.

References MemContext::db_id, MemContext::limit, MemContext::lwlock, MemContext::lwlock_idx, MemContext::lwlock_tranche, MemContext::next, shmalloc_init(), TRANCHE_NAME, veil_dbs_in_cluster(), VeilLWLock, vl_db_exists(), and vl_malloc().

Referenced by shmalloc_init().

◆ shmalloc_init()

static void shmalloc_init ( void  )
static

Attach to, creating and initialising as necessary, the shared memory control structure.

Record this for the session in shared_meminfo.

Definition at line 449 of file veil_shmem.c.

References do_vl_shmalloc(), get_shmem_context(), InitialLWLock, MemContext::lwlock, MemContext::memctl, NextLWLock(), shared_meminfo, ShmemCtl::type, ShmemCtl::veil_lwlock, veil_shmem_context_size(), and VeilLWLock.

Referenced by get_cur_context_id(), and get_shmem_context().

◆ get_cur_context_id()

static int get_cur_context_id ( )
static

Return the id (index) of the current context for this session.

Returns
The current context id

Definition at line 337 of file veil_shmem.c.

References ShmemCtl::current_context, OTHER_CONTEXT, prepared_for_switch, shmalloc_init(), and ShmemCtl::xid.

Referenced by get_cur_context(), and vl_get_shared_hash().

◆ get_cur_context()

static MemContext* get_cur_context ( )
static

Return pointer to shared memory allocated for the current context.

Returns
The current context.

Definition at line 370 of file veil_shmem.c.

References ShmemCtl::context, and get_cur_context_id().

Referenced by vl_force_context_switch(), vl_get_shared_hash(), vl_prepare_context_switch(), and vl_shmalloc().

◆ do_vl_shmalloc()

static void* do_vl_shmalloc ( MemContext context,
size_t  size 
)
static

Dynamically allocate a piece of shared memory from the current context, doing no locking.

Parameters
contextThe context in which we are operating
sizeThe size of the requested piece of memory.
Returns
Pointer to dynamically allocated memory.

Definition at line 387 of file veil_shmem.c.

References MemContext::limit, and MemContext::next.

Referenced by shmalloc_init(), and vl_shmalloc().

◆ vl_shmalloc()

void* vl_shmalloc ( size_t  size)

Dynamically allocate a piece of shared memory from the current context.

Parameters
sizeThe size of the requested piece of memory.
Returns
Pointer to dynamically allocated memory.

Definition at line 414 of file veil_shmem.c.

References do_vl_shmalloc(), get_cur_context(), and VeilLWLock.

Referenced by vl_NewBitmap(), vl_NewBitmapArray(), vl_NewInt4(), vl_NewInt4Array(), and vl_NewRange().

◆ vl_free()

void vl_free ( void *  mem)

Free a piece of shared memory within the current context.

Currently this does nothing as implementation of freeing of shared memory has been deferred.

Parameters
memPointer to the memory to be freed.

Definition at line 437 of file veil_shmem.c.

Referenced by vl_NewBitmap(), and vl_NewBitmapArray().

◆ vl_get_shared_hash()

HTAB* vl_get_shared_hash ( void  )

Return the shared hash for the current context.

Returns
Pointer to the HTAB for the current context's shared hash.

Definition at line 552 of file veil_shmem.c.

References get_cur_context(), get_cur_context_id(), get_hash0(), and get_hash1().

Referenced by ensure_init(), vl_lookup_shared_variable(), vl_lookup_variable(), and vl_next_variable().

◆ clear_hash()

static void clear_hash ( HTAB *  hash)
static

Reset one of the shared hashes.

This is one of the final steps in a context switch.

Returns
hash The shared hash that is to be reset.

Definition at line 582 of file veil_shmem.c.

References VarEntry::key.

Referenced by vl_force_context_switch(), and vl_prepare_context_switch().

◆ vl_prepare_context_switch()

bool vl_prepare_context_switch ( void  )

Prepare for a switch to the alternate context.

Switching will only be allowed if there are no transactions that may still be using the context to which we are switching, and there is no other process attempting the switch.

Returns
true if the switch preparation was successful.

Definition at line 604 of file veil_shmem.c.

References clear_hash(), ShmemCtl::context, ShmemCtl::current_context, get_cur_context(), get_hash0(), get_hash1(), MemContext::next, OTHER_CONTEXT, prepared_for_switch, ShmemCtl::switching, VeilLWLock, and ShmemCtl::xid.

Referenced by veil_perform_reset().

◆ vl_complete_context_switch()

bool vl_complete_context_switch ( void  )

Complete the context switch started by vl_prepare_context_switch().

Raise an ERROR if the context switch cannot be completed.

Returns
true if the context switch is successfully completed.

Definition at line 678 of file veil_shmem.c.

References ShmemCtl::current_context, OTHER_CONTEXT, prepared_for_switch, ShmemCtl::switching, VeilLWLock, and ShmemCtl::xid.

Referenced by veil_perform_reset().

Variable Documentation

◆ prepared_for_switch

bool prepared_for_switch = false
static

Whether the current backend is in the process of switching contexts.

If so, it will be setting up the non-current context in readiness for making it available to all other backends.

Definition at line 78 of file veil_shmem.c.

Referenced by get_cur_context_id(), vl_complete_context_switch(), vl_force_context_switch(), and vl_prepare_context_switch().

◆ VeilLWLock

LWLockId VeilLWLock = 0
static

The LWLock that Veil will use for managing concurrent access to shared memory.

It is initialised in _PG_init() to a lock id that is distinct from any that will be dynamically allocated.

Definition at line 85 of file veil_shmem.c.

Referenced by _PG_init(), get_shmem_context(), shmalloc_init(), vl_complete_context_switch(), vl_force_context_switch(), vl_prepare_context_switch(), and vl_shmalloc().

◆ InitialLWLock

LWLockId InitialLWLock = 0
static

The LWLock to be used while initially setting up shared memory and allocating a veil database-specific LWLock.

Initialised in _PG_Init()

Definition at line 92 of file veil_shmem.c.

Referenced by _PG_init(), and shmalloc_init().