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

📄 lock.c

📁 了解服务器的内部结构
💻 C
📖 第 1 页 / 共 5 页
字号:
DEBUG_DELAY;
--LOCK_asts;
DEBUG_DELAY;
#endif
}

static void blocking_action2 (
    PTR         blocking_owner_offset,
    PTR         blocked_owner_offset)
{
/**************************************
 *
 *	b l o c k i n g _ a c t i o n 2
 *
 **************************************
 *
 * Functional description
 *	Fault hander for a blocking signal.  A blocking signal
 *	is an indication (albeit a strong one) that a blocking
 *	AST is pending for the owner.  Check in with the data
 *	structure for details.
 *	The re-post code in this routine assumes that no more
 *	than one thread of execution can be running in this
 *	routine at any time.
 *
 *      IMPORTANT: Before calling this routine, acquire() should
 *	           have already been done.
 *
 *      Note that both a blocking owner offset and blocked owner
 *      offset are passed to this function.   This is for those
 *      cases where the owners are not the same.   If they are
 *      the same, then the blocked owner offset will be NULL.
 *
 **************************************/
OWN	owner;
SRQ	que;
LRQ	request;
int	(*routine)(), *arg;

ASSERT_ACQUIRED;
owner = (OWN) ABS_PTR (blocking_owner_offset);

if (!blocked_owner_offset)
    blocked_owner_offset = blocking_owner_offset;

while (owner->own_count)
    {
    que = QUE_NEXT (owner->own_blocks);
    if (que == &owner->own_blocks)
	{
	/* We've processed the own_blocks queue, reset the "we've been
	 * signaled" flag and start winding out of here
	 */
	owner->own_ast_flags &= ~OWN_signaled;
        /*post_history (his_leave_ast, blocking_owner_offset, 0, 0, TRUE);*/
	break;
	}
    request = (LRQ) ((UCHAR*) que - OFFSET (LRQ, lrq_own_blocks));
    routine = request->lrq_ast_routine;
    arg = request->lrq_ast_argument;
    remove_que (&request->lrq_own_blocks);
    if (request->lrq_flags & LRQ_blocking)
    	{
	request->lrq_flags &= ~LRQ_blocking;
	request->lrq_flags |= LRQ_blocking_seen;
    	++LOCK_header->lhb_blocks;
        post_history (his_post_ast, blocking_owner_offset, request->lrq_lock, REL_PTR (request), TRUE);
	}
    else if (request->lrq_flags & LRQ_repost)
	{
	request->lrq_type = type_null;
	insert_tail (&LOCK_header->lhb_free_requests, &request->lrq_lbl_requests);
	}
       	
    if (routine)
	{
        release (blocked_owner_offset);
	(*routine) (arg);
#ifdef NeXT
	/* make sure we're not shut down */

	if (getout)
	    break;
#endif
        acquire (blocked_owner_offset);
        owner = (OWN) ABS_PTR (blocking_owner_offset);
	}
    }
}

#if (defined WIN_NT && !defined SUPERSERVER)
static void THREAD_ROUTINE blocking_action_thread (
    PTR		*owner_offset_ptr)
{
/**************************************
 *
 *	b l o c k i n g _ a c t i o n _ t h r e a d	( W I N _ N T )
 *
 **************************************
 *
 * Functional description
 *	Thread to handle blocking signals that a process
 *	will send to itself.
 *
 **************************************/
SLONG	ret;
OWN	owner;

AST_INIT;	/* Check into scheduler as AST thread */

while (TRUE)
    {
    ret = WaitForSingleObject (blocking_event [0], INFINITE);
    AST_ENTER;
    owner = (OWN) ABS_PTR (*owner_offset_ptr);
    if ((ret && ret != WAIT_ABANDONED) || 
	!*owner_offset_ptr ||
        owner->own_process_id != LOCK_pid ||
        owner->own_owner_id == 0)
	break;
    blocking_action (*owner_offset_ptr);
    AST_EXIT;
    }

AST_EXIT;
AST_FINI;	/* Check out of scheduler as AST thread */
}
#endif

#ifdef OS2_ONLY
static void THREAD_ROUTINE blocking_action_thread (
    PTR		*owner_offset_ptr)
{
/**************************************
 *
 *	b l o c k i n g _ a c t i o n _ t h r e a d	( O S 2 )
 *
 **************************************
 *
 * Functional description
 *	Thread to handle blocking signals that a process
 *	will send to itself.
 *
 **************************************/
ULONG	status, count;
OWN	owner;

while (TRUE)
    {
    status = DosWaitEventSem (blocking_event [0], SEM_INDEFINITE_WAIT);
    owner = (OWN) ABS_PTR (*owner_offset_ptr);
    if ((status && status != ERROR_INTERRUPT) || 
	!*owner_offset_ptr ||
        owner->own_process_id != LOCK_pid ||
        owner->own_owner_id == 0)
	break;
    DosResetEventSem (blocking_event [0], &count);
    blocking_action (*owner_offset_ptr);
    }
}
#endif

#if (defined SOLARIS_MT && !defined SUPERSERVER)
static void THREAD_ROUTINE blocking_action_thread (
    PTR		*owner_offset_ptr)
{
/**************************************
 *
 *	b l o c k i n g _ a c t i o n _ t h r e a d	( S O L A R I S _ M T )
 *
 **************************************
 *
 * Functional description
 *	Thread to handle blocking signals.
 *
 **************************************/
SLONG	value;
EVENT	event_ptr;

AST_INIT;	/* Check into scheduler as AST thread */

while (TRUE)
    {
    AST_ENTER;

     /* See if main thread has requested us to go away */
    if (!*owner_offset_ptr ||
        LOCK_owner->own_process_id != LOCK_pid ||
        !LOCK_owner->own_owner_id)
	break;

    value = ISC_event_clear (LOCK_owner->own_blocking);
    blocking_action (*owner_offset_ptr);
    AST_EXIT;
    event_ptr = LOCK_owner->own_blocking;
    ISC_event_wait (1, &event_ptr, &value, 0, NULL, NULL_PTR);
    }

/* Main thread asked us to go away, do our cleanup, then tell
 * main thread we're done (see shutdown_blocking_action()).
 */

AST_EXIT;
AST_FINI;	/* Check out of scheduler as AST thread */

/* Wakeup the main thread waiting for our exit. */
/* Main thread won't wait forever, so check LOCK_owner is still mapped */

if (LOCK_owner)
    ISC_event_post (LOCK_owner->own_wakeup);
}
#endif

#ifdef DEV_BUILD
static void bug_assert (
    CONST TEXT	*string,
    ULONG	line)
{
/**************************************
 *
 *      b u g _ a s s e r t
 *
 **************************************
 *
 * Functional description
 *	Disasterous lock manager bug.  Issue message and abort process.
 *
 **************************************/
TEXT	buffer [100];
struct	lhb	LOCK_header_copy;

sprintf ((char *) buffer, "%s %ld: lock assertion failure: %s\n", 
	 __FILE__, line, string);

/* Copy the shared memory so we can examine its state when we crashed */
LOCK_header_copy = *LOCK_header;

bug (NULL, buffer);		/* Never returns */
}
#endif

static void bug (
    STATUS	*status_vector,
    CONST TEXT	*string)
{
/**************************************
 *
 *	b u g
 *
 **************************************
 *
 * Functional description
 *	Disasterous lock manager bug.  Issue message and abort process.
 *
 **************************************/
TEXT	s [128];
OWN	owner;

if (!LOCK_bugcheck++)
    {

#ifdef DEV_BUILD
#if !(defined WIN_NT || defined WINDOWS_ONLY)
    /* The lock file has some problem - copy it for later analysis */
    {
    TEXT	*lock_file;
    TEXT	buffer [256];	
    TEXT	buffer2 [256];	
    TEXT	hostname [64];
    gds__prefix_lock (buffer, LOCK_FILE);
    lock_file = buffer;
    sprintf (buffer2, lock_file, ISC_get_host (hostname, sizeof (hostname)));
    sprintf (buffer, "cp %s isc_lock1.%d", buffer2, getpid());
    system (buffer);
    }
#endif	/* WIN_NT || WINDOWS_ONLY */
#endif	/* DEV_BUILD */

    /* If the current mutex acquirer is in the same process, 
       release the mutex */

    if (LOCK_header && (LOCK_header->lhb_active_owner > 0))
	{
	owner = (OWN) ABS_PTR (LOCK_header->lhb_active_owner);
	if (owner->own_process_id == LOCK_pid) 
	    release (LOCK_header->lhb_active_owner);
	}

    if (status_vector)
	{
	*status_vector++ = gds_arg_gds;
	*status_vector++ = gds__lockmanerr;
	*status_vector++ = gds_arg_gds;
	*status_vector++ = gds__random;
	*status_vector++ = gds_arg_string;
	*status_vector++ = (STATUS) string;
	*status_vector++ = gds_arg_end;
	return;
	}
    }

sprintf (s, "Fatal lock manager error: %s, errno: %d", string, ERRNO);
gds__log (s);
ib_fprintf (ib_stderr, "%s\n", s);

#if !(defined NETWARE_386 || defined WIN_NT || defined OS2_ONLY || defined mpexl)
if (errno > 0)
    ib_fprintf (ib_stderr, "--%s\n", sys_errlist [errno]);
#endif

#ifdef DEV_BUILD
/* Make a core drop - we want to LOOK at this failure! */
abort();
#endif

exit (FINI_ERROR);
}

static BOOLEAN convert (
    PTR		request_offset,
    UCHAR	type,
    SSHORT	lck_wait,
    int		(*ast_routine)(),
    int		*ast_argument,
    STATUS	*status_vector)
{
/**************************************
 *
 *	c o n v e r t
 *
 **************************************
 *
 * Functional description
 *	Perform a lock conversion, if possible.  If the lock cannot be
 *	granted immediately, either return immediately or wait depending
 *	on a wait flag.  If the lock is granted return TRUE, otherwise
 *	return FALSE.  Note: if the conversion would cause a deadlock,
 *	FALSE is returned even if wait was requested.
 *
 **************************************/
LBL	lock;
LRQ	request;
UCHAR	temp;
BOOLEAN	new_ast;
PTR	owner_offset;

ASSERT_ACQUIRED;
request = get_request (request_offset);
lock = (LBL) ABS_PTR (request->lrq_lock);
owner_offset = request->lrq_owner;
post_history (his_convert, owner_offset, request->lrq_lock, request_offset, TRUE);
request->lrq_requested = type;
request->lrq_flags &= ~LRQ_blocking_seen;

/* Compute the state of the lock without the request. */

--lock->lbl_counts [request->lrq_state];
temp = lock_state (lock);

/* If the requested lock level is compatible with the current state
   of the lock, just grant the request.  Easy enough. */

if (COMPATIBLE (type, temp))
    {
    request->lrq_ast_routine = ast_routine;
    request->lrq_ast_argument = ast_argument;
    grant (request, lock);
    post_pending (lock);
    release (owner_offset);
    return TRUE;
    }

++lock->lbl_counts [request->lrq_state];

/* If we weren't requested to wait, just forget about the whole thing. 
   Otherwise wait for the request to be granted or rejected */

if (lck_wait)
    {
    if (request->lrq_ast_routine != ast_routine ||
	request->lrq_ast_argument != ast_argument)
	new_ast = TRUE;
    else
       	new_ast = FALSE;

    if (wait_for_request (request, lck_wait, status_vector))
	{
	ASSERT_RELEASED;
	return FALSE;
	}
    request = (LRQ) ABS_PTR (request_offset);
    if (!(request->lrq_flags & LRQ_rejected))
    	{
	if (new_ast)
	    {
	    acquire (owner_offset);
    	    request = (LRQ) ABS_PTR (request_offset);
	    request->lrq_ast_routine = ast_routine;
	    request->lrq_ast_argument = ast_argument;
	    release (owner_offset);
	    }
	ASSERT_RELEASED;
	return TRUE;
	}
    acquire (owner_offset);
    request = get_request (request_offset);
    lock = (LBL) ABS_PTR (request->lrq_lock);
    post_pending (lock);
    }

request = (LRQ) ABS_PTR (request_offset);
request->lrq_requested = request->lrq_state;
ASSERT_ACQUIRED;
++LOCK_header->lhb_denies;
if (lck_wait < 0)
    ++LOCK_header->lhb_timeouts;
release (owner_offset);
*status_vector++ = gds_arg_gds;
*status_vector++ = (lck_wait > 0) ? gds__deadlock :
			((lck_wait < 0) ? gds__lock_timeout : gds__lock_conflict);
*status_vector++ = gds_arg_end;

return FALSE;
}

static USHORT create_owner (
    STATUS	*status_vector,
    SLONG	owner_id,
    UCHAR	owner_type,
    SLONG	*owner_handle)
{
/**************************************
 *
 *	c r e a t e _ o w n e r 
 *
 **************************************
 *
 * Functional description
 *	Create an owner block.
 *
 **************************************/
SRQ	que;
OWN	owner;
USHORT	new_block;

LOCK_version = LOCK_header->lhb_version;
if (LOCK_version != LHB_VERSION)
    {

    sprintf (LOCK_bug_buffer, "inconsistent lock table version number; found %d, expected %d",
	LOCK_version, LHB_VERSION);
    bug (status_vector, LOCK_bug_buffer);
    return FAILURE;
    }

acquire (DUMMY_OWNER_CREATE);		/* acquiring owner is being created */

/* Look for a previous instance of owner.  If we find one, get rid of it. */

QUE_LOOP (LOCK_header->lhb_owners, que)
    {
    owner = (OWN) ((UCHAR*) que - OFFSET (OWN, own_lhb_owners));
    if (owner->own_owner_id == owner_id && owner->own_owner_type == owner_type)
	{
	purge_owner (DUMMY_OWNER_CREATE, owner); /* purging owner_offset has not been set yet */
	break;
	}
    }

/* Allocate an owner block */

if (QUE_EMPTY (LOCK_header->lhb_free_owners))
    {
    if (!(owner = (OWN) alloc (sizeof (struct own), status_vector)))
	{
	release_mutex();
	return FAILURE;
	}
    new_block = OWN_BLOCK_new;
    }
else
    {
    owner = (OWN) ((UCHAR*) QUE_NEXT (LOCK_header->lhb_free_owners) - 
	OFFSET (OWN, own_lhb_owners));
    remove_que (&owner->own_lhb_owners);
    new_block = OWN_BLOCK_reused;
    }

init_owner_block (owner, owner_type, owner_id, new_block);

/* cannot ASSERT_ACQUIRED; here - owner not setup */
insert_tail (&LOCK_

⌨️ 快捷键说明

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