Skip to content

File critical_section.h

File List > cubrid > src > thread > critical_section.h

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */


/*
 * critical_section.h - Definitions for critical section interface.
 */

#ifndef _CRITICAL_SECTION_H_
#define _CRITICAL_SECTION_H_

#ident "$Id$"

#include "dbtype_def.h"
#include "porting.h"        // for pthread, STATIC_CAST
#include "thread_compat.hpp"

#if !defined(WINDOWS)
#include <pthread.h>
#endif /* !WINDOWS */
#if !defined(WINDOWS)
#include <sys/time.h>
#endif /* !WINDOWS */
#if defined (WINDOWS)
#include <WinSock2.h>
#endif // WINDOWS

#if !defined (SERVER_MODE) && !defined (SA_MODE)
#error critical_section.h belongs to server or stand-alone modules.
#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */

enum
{
  INF_WAIT = -1,        /* INFINITE WAIT */
  NOT_WAIT = 0          /* NO WAIT */
};

/*
 * These are the user defined lock definitions. When adding more locks, also
 * add initialization entries in critical_section.c
 */
enum
{
  CSECT_WFG = 0,        /* Latch for wait-for-graph */
  CSECT_LOG,            /* Latch for log manager */
  CSECT_LOCATOR_SR_CLASSNAME_TABLE, /* Latch for classname to classOID entries */
  CSECT_QPROC_QUERY_TABLE,  /* Latch for query manager table */
  CSECT_QPROC_LIST_CACHE,   /* Latch for query result(list file) cache (mht) */
  CSECT_DISK_CHECK,     /* Block changes on disk cache during check */
  CSECT_CNV_FMT_LEXER,      /* Latch for value/string format translation lexer */
  CSECT_HEAP_CHNGUESS,      /* Latch for schema change */

  CSECT_TRAN_TABLE,     /* Latch for transaction table */
  CSECT_CT_OID_TABLE,
  CSECT_HA_SERVER_STATE,    /* Latch for HA server mode change */
  CSECT_COMPACTDB_ONE_INSTANCE, /* Latch for compactdb */
  CSECT_ACL,            /* Latch for accessible IP list table */
  CSECT_PARTITION_CACHE,    /* Latch for partitions cache */
  CSECT_EVENT_LOG_FILE,     /* Latch for event log file */
  CSECT_TRACE_LOG_FILE,     /* Latch for trace log file */
  CSECT_LOG_ARCHIVE,        /* Latch for log_Gl.archive */
  CSECT_ACCESS_STATUS,      /* Latch for user access status */
  CSECT_LAST
};

static const int CRITICAL_SECTION_COUNT = STATIC_CAST (int, CSECT_LAST);

typedef enum
{
  SYNC_TYPE_NONE,

  SYNC_TYPE_CSECT,      /* critical section primitive */
  SYNC_TYPE_RWLOCK,     /* rwlock primitive */
  SYNC_TYPE_RMUTEX,     /* re-entrant mutex */
  SYNC_TYPE_MUTEX,      /* simple mutex */

  SYNC_TYPE_LAST = SYNC_TYPE_MUTEX,
  SYNC_TYPE_COUNT = SYNC_TYPE_LAST,
  SYNC_TYPE_ALL = SYNC_TYPE_LAST
} SYNC_PRIMITIVE_TYPE;

typedef struct sync_stats
{
  SYNC_PRIMITIVE_TYPE type;
  const char *name;

  unsigned int nenter;      /* total number of acquisition. */
  unsigned int nwait;       /* total number of waiting. only available for SYNC_TYPE_CSECT */
  unsigned int nreenter;    /* total number of re-acquisition. available for SYNC_TYPE_CSECT, SYNC_TYPE_RMUTEX */

  struct timeval total_elapsed; /* total elapsed time to acquire the synchronization primitive */
  struct timeval max_elapsed;   /* max elapsed time to acquire the synchronization primitive */
} SYNC_STATS;

typedef struct sync_critical_section
{
  const char *name;
  int cs_index;
  pthread_mutex_t lock;     /* read/write monitor lock */
  int rwlock;           /* >0 = # readers, <0 = writer, 0 = none */
  unsigned int waiting_readers; /* # of waiting readers */
  unsigned int waiting_writers; /* # of waiting writers */
  pthread_cond_t readers_ok;    /* start waiting readers */
  THREAD_ENTRY *waiting_writers_queue;  /* queue of waiting writers */
  THREAD_ENTRY *waiting_promoters_queue;    /* queue of waiting promoters */
  thread_id_t owner;        /* CS owner writer */
  int tran_index;       /* transaction id acquiring CS */
  SYNC_STATS *stats;
} SYNC_CRITICAL_SECTION;

typedef struct sync_rwlock
{
  const char *name;
  pthread_mutex_t read_lock;    /* read lock. Only readers will use it. */
  pthread_mutex_t global_lock;  /* global lock */
  int num_readers;      /* # of readers. Only readers will use it. */
  SYNC_STATS *stats;
} SYNC_RWLOCK;

typedef struct sync_rmutex
{
  const char *name;
  pthread_mutex_t lock;     /* mutex */
  thread_id_t owner;        /* owner thread id */
  int lock_cnt;         /* # of times that owner enters */
  SYNC_STATS *stats;
} SYNC_RMUTEX;

extern int csect_initialize_static_critical_sections (void);
extern int csect_finalize_static_critical_sections (void);

extern int csect_enter (THREAD_ENTRY * thread_p, int cs_index, int wait_secs);
extern int csect_enter_as_reader (THREAD_ENTRY * thread_p, int cs_index, int wait_secs);
extern int csect_demote (THREAD_ENTRY * thread_p, int cs_index, int wait_secs);
extern int csect_promote (THREAD_ENTRY * thread_p, int cs_index, int wait_secs);
extern int csect_exit (THREAD_ENTRY * thread_p, int cs_index);

#if defined (SERVER_MODE)
extern const char *csect_name_at (int cs_index);
#else // not SERVER_MODE = SA_MODE
static inline const char *
csect_name_at (int cs_index)
{
  return "UNKNOWN";
}
#endif // not SERVER_MODE = SA_MODE
extern int csect_initialize_critical_section (SYNC_CRITICAL_SECTION * cs_ptr, const char *name);
extern int csect_finalize_critical_section (SYNC_CRITICAL_SECTION * cs_ptr);
extern int csect_enter_critical_section (THREAD_ENTRY * thread_p, SYNC_CRITICAL_SECTION * cs_ptr, int wait_secs);
extern int csect_enter_critical_section_as_reader (THREAD_ENTRY * thread_p, SYNC_CRITICAL_SECTION * cs_ptr,
                           int wait_secs);
extern int csect_exit_critical_section (THREAD_ENTRY * thread_p, SYNC_CRITICAL_SECTION * cs_ptr);

extern int csect_check_own (THREAD_ENTRY * thread_p, int cs_index);

extern void csect_dump_statistics (FILE * fp);

extern int csect_start_scan (THREAD_ENTRY * thread_p, int show_type, DB_VALUE ** arg_values, int arg_cnt, void **ctx);

extern int rwlock_initialize (SYNC_RWLOCK * rwlock, const char *name);
extern int rwlock_finalize (SYNC_RWLOCK * rwlock);

extern int rwlock_read_lock (SYNC_RWLOCK * rwlock);
extern int rwlock_read_unlock (SYNC_RWLOCK * rwlock);

extern int rwlock_write_lock (SYNC_RWLOCK * rwlock);
extern int rwlock_write_unlock (SYNC_RWLOCK * rwlock);

extern int sync_initialize_sync_stats (void);
extern int sync_finalize_sync_stats (void);

extern void rwlock_dump_statistics (FILE * fp);

extern int rmutex_initialize (SYNC_RMUTEX * rmutex, const char *name);
extern int rmutex_finalize (SYNC_RMUTEX * rmutex);

extern int rmutex_lock (THREAD_ENTRY * thread_p, SYNC_RMUTEX * rmutex);
extern int rmutex_unlock (THREAD_ENTRY * thread_p, SYNC_RMUTEX * rmutex);

extern void rmutex_dump_statistics (FILE * fp);

extern void sync_dump_statistics (FILE * fp, SYNC_PRIMITIVE_TYPE type);

#if !defined(SERVER_MODE)
#define csect_initialize_critical_section(a, b)
#define csect_finalize_critical_section(a)
#define csect_enter(a, b, c) NO_ERROR
#define csect_enter_as_reader(a, b, c) NO_ERROR
#define csect_exit(a, b)
#define csect_enter_critical_section(a, b, c)
#define csect_enter_critical_section_as_reader(a, b, c)
#define csect_exit_critical_section(a, b)
#define csect_check_own(a, b) 1
#define csect_start_scan NULL

#define rwlock_initialize(a, b) NO_ERROR
#define rwlock_finalize(a) NO_ERROR
#define rwlock_read_lock(a) NO_ERROR
#define rwlock_read_unlock(a) NO_ERROR
#define rwlock_write_lock(a) NO_ERROR
#define rwlock_write_unlock(a) NO_ERROR

#define rmutex_initialize(a, b) NO_ERROR
#define rmutex_finalize(a) NO_ERROR
#define rmutex_lock(a, b) NO_ERROR
#define rmutex_unlock(a, b) NO_ERROR
#endif /* !SERVER_MODE */

#endif /* _CRITICAL_SECTION_H_ */