⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lock.c

📁 了解服务器的内部结构
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *	PROGRAM:	JRD Lock Manager
 *	MODULE:		lock.c
 *	DESCRIPTION:	Generic ISC Lock Manager
 *
 * The contents of this file are subject to the Interbase Public
 * License Version 1.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.Inprise.com/IPL.html
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code was created by Inprise Corporation
 * and its predecessors. Portions created by Inprise Corporation are
 * Copyright (C) Inprise Corporation.
 *
 * All Rights Reserved.
 * Contributor(s): ______________________________________.
 */

#include "../jrd/time.h"
#include "../jrd/ib_stdio.h"
#include "../jrd/common.h"
#include "../jrd/thd.h"
#include "../jrd/isc.h"
#ifdef LINKS_EXIST
#include "../isc_lock/lock.h"
#include "../isc_lock/lock_proto.h"
#else
#include "../lock/lock.h"
#include "../lock/lock_proto.h"
#endif /* LINKS_EXIST */  
#include "../jrd/codes.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_proto.h"
#include "../jrd/isc_i_proto.h"
#include "../jrd/isc_s_proto.h"
#include "../jrd/sch_proto.h"
#include "../jrd/thd_proto.h"
#include <errno.h>

#ifdef WINDOWS_ONLY
#include "../jrd/loiter.h"
#define getpid          GetCurrentTask
#endif
   
#ifdef sparc
#ifndef SOLARIS
#include <vfork.h>
#endif
#endif

#ifdef NeXT
#include <mach/message.h>
#include <mach/port.h>
#include <mach/kern_return.h>
#endif

#ifdef mpexl
#include <mpe.h>
#include "../jrd/mpexl.h"

#define MUTEX		lock_manager_mutex
#endif

#if ( defined DELTA || defined IMP )
#define waitpid(x,y,z)	wait (y)
#endif

#ifdef NETWARE_386
#define getpid		GetNLMID
#define USE_EVENTS
#endif

#ifdef OS2_ONLY
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#include <os2.h>
#include <process.h>
#define MUTEX		lock_manager_mutex
#define USE_EVENTS
#endif

#if (defined UNIX && !defined NeXT)
#define USE_EVENTS
#ifndef ANY_THREADING   /* #if !(defined SOLARIS || defined POSIX_THREADS) */
#define STATIC_SEMAPHORES
#endif /* ANY_THREADING */
#endif /* (defined UNIX && !defined NeXT) */

#ifdef WIN_NT
#include <process.h>
#define MUTEX		lock_manager_mutex
#define ERRNO		GetLastError()
#endif

#ifdef MANAGER_PROCESS
#include <sys/stat.h>
#define statistics	stat
static BOOLEAN	LOCK_post_manager;
#endif

#ifdef DEV_BUILD
#define ASSERT_ACQUIRED current_is_active_owner (TRUE,  __LINE__)
#define ASSERT_RELEASED current_is_active_owner (FALSE, __LINE__)
#define VALIDATE_LOCK_TABLE
#if ((defined MMAP_SUPPORTED) && !(defined SUPERSERVER))
#define LOCK_DEBUG_ACQUIRE
#endif
#endif

#ifdef LOCK_DEBUG_ACQUIRE
#define DEBUG_ACQUIRE_INTERVAL 5000
static ULONG	debug_acquire_count = 0;
#endif

#ifndef ASSERT_ACQUIRED
#define	ASSERT_ACQUIRED	/* nothing */
#endif

#ifndef ASSERT_RELEASED
#define	ASSERT_RELEASED	/* nothing */
#endif

#ifdef DEV_BUILD
#define CHECK(x)	{ if (!(x)) bug_assert ("consistency check", __LINE__); }
#endif

#ifndef CHECK
#define CHECK(x)	/* nothing */
#endif

#ifdef DEBUG
#define DEBUG_MANAGER "manager"	
#define DEBUG_TRACE
#endif

#ifdef DEBUG_TRACE
#define LOCK_TRACE(x)	{ time_t t; (void) time (&t); ib_printf ("%s", ctime(&t) ); ib_printf x ; ib_fflush (ib_stdout); }
#endif

#ifdef DEBUG
SSHORT	LOCK_debug_level = 0;
#define DEBUG_MSG(l,x)	if ((l) <= LOCK_debug_level) { time_t t; (void) time (&t); ib_printf ("%s", ctime(&t) ); ib_printf x ; ib_fflush (ib_stdout); gds__log x ; }
#endif

#ifndef DEBUG_MSG
#define DEBUG_MSG(l,x)	/* nothing */
#endif

#ifndef LOCK_TRACE
#define LOCK_TRACE(x)	/* nothing */
#endif

/* Debug delay is used to create nice big windows for signals or other
 * events to occur in - eg: slow down the code to try and make
 * timing race conditions show up
 */
#ifdef DEBUG
#define	DEBUG_DELAY	debug_delay (__LINE__)
#endif

#ifndef DEBUG_DELAY
#define DEBUG_DELAY	/* nothing */
#endif

#ifndef ERRNO
#define ERRNO		errno
#endif

#ifndef MUTEX
#define MUTEX		LOCK_header->lhb_mutex
#endif

#ifndef MAXPATHLEN
#define MAXPATHLEN	256
#endif

#ifndef SV_INTERRUPT
#define SV_INTERRUPT	0
#endif

#define DUMMY_OWNER_CREATE	((PTR) -1)
#define DUMMY_OWNER_DELETE	((PTR) -2)
#define DUMMY_OWNER_SHUTDOWN	((PTR) -3)

#if !(defined linux || defined NETWARE_386 || defined WIN_NT || defined OS2_ONLY || defined mpexl)
extern SCHAR	*sys_errlist[];
#endif

static void	acquire (PTR);
static UCHAR	*alloc (SSHORT, STATUS *);
static LBL	alloc_lock (USHORT, STATUS *);
static USHORT	alloc_semaphore (OWN, STATUS *);
static void	blocking_action (PTR);
static void     blocking_action2 (PTR, PTR);
static void THREAD_ROUTINE blocking_action_thread (PTR *);
static void	bug (STATUS *, CONST TEXT *);
#ifdef DEV_BUILD
static void	bug_assert (CONST TEXT *, ULONG);
#endif
static BOOLEAN	convert (PTR, UCHAR, SSHORT, FPTR_INT, int *, STATUS *);
static USHORT	create_owner (STATUS *, SLONG, UCHAR, SLONG *);
#ifdef DEV_BUILD
static void	current_is_active_owner (BOOLEAN, ULONG);
#endif
static void	deadlock_clear (void);
static LRQ	deadlock_scan (OWN, LRQ);
static LRQ	deadlock_walk (LRQ, BOOLEAN *);
static void	dequeue (PTR);
#ifdef DEBUG
static void	debug_delay (ULONG);
#endif
static void	exit_handler (void *);
static LBL	find_lock (PTR, USHORT, UCHAR *, USHORT, USHORT *);
static USHORT	fork_lock_manager (STATUS *);
static OWN	get_manager (BOOLEAN);
static LRQ	get_request (PTR);
static void	grant (LRQ, LBL);
static PTR	grant_or_que (LRQ, LBL, SSHORT);
static STATUS	init_lock_table (STATUS *);
static void	init_owner_block (OWN, UCHAR, ULONG, USHORT);
static void	lock_alarm_handler (EVENT);
static void	lock_initialize (void *, SH_MEM, int);
static void	insert_data_que (LBL);
static void	insert_tail (SRQ, SRQ);
static USHORT	lock_state (LBL);
static void	port_waker (PTR *);
static void	post_blockage (LRQ, LBL, BOOLEAN);
static void	post_history (USHORT, PTR, PTR, PTR, BOOLEAN);
static void	post_pending (LBL);
static void	post_wakeup (OWN);
#ifndef SUPERSERVER
static BOOLEAN	probe_owners (PTR);
#endif
static void	purge_owner (PTR, OWN);
static void	remove_que (SRQ);
static void	release (PTR);
static void	release_mutex (void);
static void	release_request (LRQ);
static void	release_semaphore (OWN);
static void	shutdown_blocking_thread (STATUS *);
static int      signal_owner (OWN, PTR);
#ifdef VALIDATE_LOCK_TABLE
static void	validate_lhb (LHB);
static void	validate_shb (PTR);
static void	validate_owner (PTR, USHORT);
static void	validate_lock (PTR, USHORT, PTR);
static void	validate_request (PTR, USHORT, USHORT);
static void	validate_block (PTR);
#endif
static USHORT	wait_for_request (LRQ, SSHORT, STATUS *);
static void	wakeup_action (PTR *);

static struct own	LOCK_process_owner;  /* Place holder */
static SSHORT	LOCK_bugcheck = 0;
static LHB	VOLATILE LOCK_header = NULL;
static PTR	LOCK_owner_offset = 0;
static OWN	LOCK_owner = NULL_PTR;
static SSHORT	VOLATILE LOCK_asts = -1;
static int	LOCK_pid = 0, LOCK_version = 0;
static SLONG	LOCK_shm_size = 0, LOCK_sem_count = 0;
#if (defined SOLARIS_MT && !defined SUPERSERVER)
static SLONG    LOCK_solaris_stall = 60; /* seconds - def value for solaris stall */
#endif
static SLONG	LOCK_block_signal = 0;
#ifdef WAKEUP_SIGNAL
static SLONG	LOCK_wakeup_signal = 0;
#endif
static SLONG	LOCK_ordering = 0;
static SLONG	LOCK_hash_slots;
static SLONG	LOCK_scan_interval;
static SLONG	LOCK_acquire_spins = 0;
static SH_MEM_T	LOCK_data;
static BOOLEAN	start_manager = FALSE;
static	TEXT	LOCK_bug_buffer [128];

#ifdef mpexl
static MTX_T	lock_manager_mutex [1];
#endif

#ifdef NeXT
static int	condition_set;		/* flag used between threads */
static port_t	alarm_port;		/* alarm thread's port */
static SCHAR	message_buf [24];	/* used to send messages to alarm thd */
static SCHAR	message_buf1 [24];	/* used to receive above messages */
static msg_header_t *null_msg;
static msg_header_t *null_msg1;
static int	VOLATILE getout = 0;	/* flag used to stop alarm and blocking
					   threads from continuing after the
					   main thread shuts down (LOCK_fini) */
#endif

#ifdef OS2_ONLY
static MTX_T	lock_manager_mutex [1];
static HEV	blocking_event [1];
#endif

#ifdef WIN_NT
static MTX_T	lock_manager_mutex [1];
#ifndef SUPERSERVER
static HANDLE	blocking_event [1], wakeup_event [1];
#endif
#endif

static struct ipccfg	LOCK_hdrtbl [] = {
/* 5.5 SCO Port: Classic server on SCO - following is not supported */
#if (!(defined WIN_NT) && !(defined SCO_EV))
	"V4_LOCK_MEM_SIZE",	-1,	&LOCK_shm_size,		0,	0,
	"ANY_LOCK_MEM_SIZE",	-1,	&LOCK_shm_size,		-1,	0,
#endif
#ifdef STATIC_SEMAPHORES
	"V4_LOCK_SEM_COUNT",	-1,	&LOCK_sem_count,	0,	0,
	"ANY_LOCK_SEM_COUNT",	-1,	&LOCK_sem_count,	-1,	0,
#endif
	"V4_LOCK_SIGNAL",	-1,	&LOCK_block_signal,	0,	0,
	"ANY_LOCK_SIGNAL",	-1,	&LOCK_block_signal,	-1,	0,
	"V4_LOCK_GRANT_ORDER",	-1,	&LOCK_ordering,		0,	0,
	"LOCK_HASH_SLOTS",	-1,	&LOCK_hash_slots,	0,	0,
	"DEADLOCK_TIMEOUT",	-1,	&LOCK_scan_interval,	0,	0,
	"LOCK_ACQUIRE_SPINS",	-1,	&LOCK_acquire_spins,	0,	0,
#if (defined SOLARIS_MT && !defined SUPERSERVER)
        "V4_SOLARIS_STALL_VALUE",-1,	&LOCK_solaris_stall,   	0,      0,
#endif
	NULL,			0,	NULL,			0,	0
};

#ifndef mpexl
#define GET_TIME	time (NULL)
#else
#define GET_TIME	TIMER()
#endif

#define WAIT_TIME	10
#define HASH_MIN_SLOTS	101
#define HASH_MAX_SLOTS	2048
#define HISTORY_BLOCKS	256
#define LOCKMANTIMEOUT	300

#if (defined SOLARIS_MT && !defined SUPERSERVER)
#define STARVATION_THRESHHOLD	500	/* acquires of lock table */
#define SOLARIS_MIN_STALL       0
#define SOLARIS_MAX_STALL       200
#define SOLARIS_MAX_STALL       200	/* Seconds */
#endif

#define OWN_BLOCK_new		1
#define OWN_BLOCK_reused	2
#define OWN_BLOCK_dummy		3

#ifndef LOCK_MANAGER
#define LOCK_MANAGER	"bin/gds_lock_mgr"
#endif

#ifdef SHLIB_DEFS
#define sys_errlist	(*_libgds_sys_errlist)
#ifdef IMP
#define wait		(*_libgds_wait)
#else
#define waitpid		(*_libgds_waitpid)
#endif
#define execl		(*_libgds_execl)
#define _exit		(*_libgds__exit)
#define statistics	(*_libgds_stat)
#define chmod		(*_libgds_chmod)

extern SCHAR		*sys_errlist [];
#ifdef IMP
extern int		wait();
#else
extern int		waitpid();
#endif
extern int		execl();
extern void		_exit();
extern int		statistics();
extern int		chmod();
#endif

static CONST UCHAR	compatibility[] = {

/*				Shared	Prot	Shared	Prot
		none	null	 Read	Read	Write	Write	Exclusive */

/* none */	1,	  1,	   1,	  1,	  1,	  1,	  1,
/* null */	1,	  1,	   1,	  1,	  1,	  1,	  1,
/* SR */	1,	  1,	   1,     1,	  1,	  1,	  0,
/* PR */	1,	  1,	   1,	  1,	  0,	  0,	  0,
/* SW */	1,	  1,	   1,	  0,	  1,	  0,	  0,
/* PW */	1,	  1,	   1,	  0,	  0,	  0,	  0,
/* EX */	1,	  1,	   0,	  0,	  0,	  0,	  0 };

#define COMPATIBLE(st1, st2)	compatibility [st1 * LCK_max + st2]

int LOCK_convert (
    PTR		request_offset,
    UCHAR	type,
    SSHORT	lck_wait,
    int		(*ast_routine)(void *),
    void	*ast_argument,
    STATUS	*status_vector)
{
/**************************************
 *
 *	L O C K _ c o n v e r t
 *
 **************************************
 *
 * Functional description
 *	Perform a lock conversion, if possible.
 *
 **************************************/
LRQ	request;
OWN	owner;
LBL	lock;

#ifdef  WINDOWS_ONLY
lck_wait = 0;		/* LIBS is always no wait */
#endif

LOCK_TRACE (("LOCK_convert (%d, %d)\n", type, lck_wait));

request = get_request (request_offset);
owner = (OWN) ABS_PTR (request->lrq_owner);
if (!owner->own_count)
    return FALSE;

acquire (request->lrq_owner);
owner = NULL;					/* remap */
++LOCK_header->lhb_converts;
request = (LRQ) ABS_PTR (request_offset);	/* remap */
lock = (LBL) ABS_PTR (request->lrq_lock);
if (lock->lbl_series < LCK_MAX_SERIES)
    ++LOCK_header->lhb_operations [lock->lbl_series];
else
    ++LOCK_header->lhb_operations [0];

return (convert (request_offset, type, lck_wait, ast_routine, ast_argument, status_vector));
}

int LOCK_deq (
    PTR		request_offset)
{
/**************************************
 *
 *	L O C K _ d e q 
 *
 **************************************
 *
 * Functional description
 *	Release an outstanding lock.
 *
 **************************************/
LRQ	request;
OWN	owner;
PTR	owner_offset;
LBL	lock;

LOCK_TRACE (("LOCK_deq (%d)\n", request_offset));

request = get_request (request_offset);
owner_offset = request->lrq_owner;
owner = (OWN) ABS_PTR (owner_offset);
if (!owner->own_count)
    return FALSE;

acquire (owner_offset);
owner = NULL;					/* remap */
++LOCK_header->lhb_deqs;
request = (LRQ) ABS_PTR (request_offset);	/* remap */
lock = (LBL) ABS_PTR (request->lrq_lock);
if (lock->lbl_series < LCK_MAX_SERIES)
    ++LOCK_header->lhb_operations [lock->lbl_series];
else
    ++LOCK_header->lhb_operations [0];

dequeue (request_offset);
release (owner_offset);
return TRUE;
}

UCHAR LOCK_downgrade (
    PTR		request_offset,
    STATUS	*status_vector)
{
/**************************************
 *
 *	L O C K _ d o w n g r a d e
 *
 **************************************
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -