mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-30 04:26:45 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			185 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*-
 | |
|  * See the file LICENSE for redistribution information.
 | |
|  *
 | |
|  * Copyright (c) 1996-2002
 | |
|  *	Sleepycat Software.  All rights reserved.
 | |
|  */
 | |
| 
 | |
| #include "db_config.h"
 | |
| 
 | |
| #ifndef lint
 | |
| static const char revid[] = "$Id: mut_fcntl.c,v 11.21 2002/05/31 19:37:45 bostic Exp $";
 | |
| #endif /* not lint */
 | |
| 
 | |
| #ifndef NO_SYSTEM_INCLUDES
 | |
| #include <sys/types.h>
 | |
| 
 | |
| #include <fcntl.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| #include "db_int.h"
 | |
| 
 | |
| /*
 | |
|  * __db_fcntl_mutex_init --
 | |
|  *	Initialize a DB mutex structure.
 | |
|  *
 | |
|  * PUBLIC: int __db_fcntl_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
 | |
|  */
 | |
| int
 | |
| __db_fcntl_mutex_init(dbenv, mutexp, offset)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DB_MUTEX *mutexp;
 | |
| 	u_int32_t offset;
 | |
| {
 | |
| 	u_int32_t save;
 | |
| 
 | |
| 	/*
 | |
| 	 * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
 | |
| 	 * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
 | |
| 	 * flag.  This is safe because even if this flag was never explicitly
 | |
| 	 * set, but happened to be set in memory, it will never be checked or
 | |
| 	 * acted upon.
 | |
| 	 */
 | |
| 	save = F_ISSET(mutexp, MUTEX_MPOOL);
 | |
| 	memset(mutexp, 0, sizeof(*mutexp));
 | |
| 	F_SET(mutexp, save);
 | |
| 
 | |
| 	/*
 | |
| 	 * This is where we decide to ignore locks we don't need to set -- if
 | |
| 	 * the application is private, we don't need any locks.
 | |
| 	 */
 | |
| 	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
 | |
| 		F_SET(mutexp, MUTEX_IGNORE);
 | |
| 		return (0);
 | |
| 	}
 | |
| 
 | |
| 	mutexp->off = offset;
 | |
| #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 | |
| 	mutexp->reg_off = INVALID_ROFF;
 | |
| #endif
 | |
| 	F_SET(mutexp, MUTEX_INITED);
 | |
| 
 | |
| 	return (0);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __db_fcntl_mutex_lock
 | |
|  *	Lock on a mutex, blocking if necessary.
 | |
|  *
 | |
|  * PUBLIC: int __db_fcntl_mutex_lock __P((DB_ENV *, DB_MUTEX *));
 | |
|  */
 | |
| int
 | |
| __db_fcntl_mutex_lock(dbenv, mutexp)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DB_MUTEX *mutexp;
 | |
| {
 | |
| 	struct flock k_lock;
 | |
| 	int locked, ms, waited;
 | |
| 
 | |
| 	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
 | |
| 		return (0);
 | |
| 
 | |
| 	/* Initialize the lock. */
 | |
| 	k_lock.l_whence = SEEK_SET;
 | |
| 	k_lock.l_start = mutexp->off;
 | |
| 	k_lock.l_len = 1;
 | |
| 
 | |
| 	for (locked = waited = 0;;) {
 | |
| 		/*
 | |
| 		 * Wait for the lock to become available; wait 1ms initially,
 | |
| 		 * up to 1 second.
 | |
| 		 */
 | |
| 		for (ms = 1; mutexp->pid != 0;) {
 | |
| 			waited = 1;
 | |
| 			__os_yield(NULL, ms * USEC_PER_MS);
 | |
| 			if ((ms <<= 1) > MS_PER_SEC)
 | |
| 				ms = MS_PER_SEC;
 | |
| 		}
 | |
| 
 | |
| 		/* Acquire an exclusive kernel lock. */
 | |
| 		k_lock.l_type = F_WRLCK;
 | |
| 		if (fcntl(dbenv->lockfhp->fd, F_SETLKW, &k_lock))
 | |
| 			return (__os_get_errno());
 | |
| 
 | |
| 		/* If the resource is still available, it's ours. */
 | |
| 		if (mutexp->pid == 0) {
 | |
| 			locked = 1;
 | |
| 			__os_id(&mutexp->pid);
 | |
| 		}
 | |
| 
 | |
| 		/* Release the kernel lock. */
 | |
| 		k_lock.l_type = F_UNLCK;
 | |
| 		if (fcntl(dbenv->lockfhp->fd, F_SETLK, &k_lock))
 | |
| 			return (__os_get_errno());
 | |
| 
 | |
| 		/*
 | |
| 		 * If we got the resource lock we're done.
 | |
| 		 *
 | |
| 		 * !!!
 | |
| 		 * We can't check to see if the lock is ours, because we may
 | |
| 		 * be trying to block ourselves in the lock manager, and so
 | |
| 		 * the holder of the lock that's preventing us from getting
 | |
| 		 * the lock may be us!  (Seriously.)
 | |
| 		 */
 | |
| 		if (locked)
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	if (waited)
 | |
| 		++mutexp->mutex_set_wait;
 | |
| 	else
 | |
| 		++mutexp->mutex_set_nowait;
 | |
| 	return (0);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __db_fcntl_mutex_unlock --
 | |
|  *	Release a lock.
 | |
|  *
 | |
|  * PUBLIC: int __db_fcntl_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
 | |
|  */
 | |
| int
 | |
| __db_fcntl_mutex_unlock(dbenv, mutexp)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DB_MUTEX *mutexp;
 | |
| {
 | |
| 	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
 | |
| 		return (0);
 | |
| 
 | |
| #ifdef DIAGNOSTIC
 | |
| #define	MSG		"mutex_unlock: ERROR: released lock that was unlocked\n"
 | |
| #ifndef	STDERR_FILENO
 | |
| #define	STDERR_FILENO	2
 | |
| #endif
 | |
| 	if (mutexp->pid == 0)
 | |
| 		write(STDERR_FILENO, MSG, sizeof(MSG) - 1);
 | |
| #endif
 | |
| 
 | |
| 	/*
 | |
| 	 * Release the resource.  We don't have to acquire any locks because
 | |
| 	 * processes trying to acquire the lock are checking for a pid set to
 | |
| 	 * 0/non-0, not to any specific value.
 | |
| 	 */
 | |
| 	mutexp->pid = 0;
 | |
| 
 | |
| 	return (0);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __db_fcntl_mutex_destroy --
 | |
|  *	Destroy a DB_MUTEX.
 | |
|  *
 | |
|  * PUBLIC: int __db_fcntl_mutex_destroy __P((DB_MUTEX *));
 | |
|  */
 | |
| int
 | |
| __db_fcntl_mutex_destroy(mutexp)
 | |
| 	DB_MUTEX *mutexp;
 | |
| {
 | |
| 	COMPQUIET(mutexp, NULL);
 | |
| 
 | |
| 	return (0);
 | |
| }
 | 
