Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

mut_fcntl.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: mut_fcntl.c,v 12.13 2005/11/01 14:42:17 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <fcntl.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "dbinc/mutex_int.h"
00022 
00023 /*
00024  * __db_fcntl_mutex_init --
00025  *      Initialize a fcntl mutex.
00026  *
00027  * PUBLIC: int __db_fcntl_mutex_init __P((DB_ENV *, db_mutex_t, u_int32_t));
00028  */
00029 int
00030 __db_fcntl_mutex_init(dbenv, mutex, flags)
00031         DB_ENV *dbenv;
00032         db_mutex_t mutex;
00033         u_int32_t flags;
00034 {
00035         COMPQUIET(dbenv, NULL);
00036         COMPQUIET(mutex, MUTEX_INVALID);
00037         COMPQUIET(flags, 0);
00038 
00039         return (0);
00040 }
00041 
00042 /*
00043  * __db_fcntl_mutex_lock
00044  *      Lock on a mutex, blocking if necessary.
00045  *
00046  * PUBLIC: int __db_fcntl_mutex_lock __P((DB_ENV *, db_mutex_t));
00047  */
00048 int
00049 __db_fcntl_mutex_lock(dbenv, mutex)
00050         DB_ENV *dbenv;
00051         db_mutex_t mutex;
00052 {
00053         DB_MUTEX *mutexp;
00054         DB_MUTEXMGR *mtxmgr;
00055         DB_MUTEXREGION *mtxregion;
00056         struct flock k_lock;
00057         int locked, ms, ret;
00058 
00059         if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00060                 return (0);
00061 
00062         mtxmgr = dbenv->mutex_handle;
00063         mtxregion = mtxmgr->reginfo.primary;
00064         mutexp = MUTEXP_SET(mutex);
00065 
00066 #ifdef HAVE_STATISTICS
00067         if (F_ISSET(mutexp, DB_MUTEX_LOCKED))
00068                 ++mutexp->mutex_set_wait;
00069         else
00070                 ++mutexp->mutex_set_nowait;
00071 #endif
00072 
00073         /* Initialize the lock. */
00074         k_lock.l_whence = SEEK_SET;
00075         k_lock.l_start = mutex;
00076         k_lock.l_len = 1;
00077 
00078         for (locked = 0;;) {
00079                 /*
00080                  * Wait for the lock to become available; wait 1ms initially,
00081                  * up to 1 second.
00082                  */
00083                 for (ms = 1; F_ISSET(mutexp, DB_MUTEX_LOCKED);) {
00084                         __os_yield(NULL, ms * USEC_PER_MS);
00085                         if ((ms <<= 1) > MS_PER_SEC)
00086                                 ms = MS_PER_SEC;
00087                 }
00088 
00089                 /* Acquire an exclusive kernel lock. */
00090                 k_lock.l_type = F_WRLCK;
00091                 if (fcntl(dbenv->lockfhp->fd, F_SETLKW, &k_lock))
00092                         goto err;
00093 
00094                 /* If the resource is still available, it's ours. */
00095                 if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00096                         locked = 1;
00097 
00098                         F_SET(mutexp, DB_MUTEX_LOCKED);
00099                         dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
00100                         CHECK_MTX_THREAD(dbenv, mutexp);
00101                 }
00102 
00103                 /* Release the kernel lock. */
00104                 k_lock.l_type = F_UNLCK;
00105                 if (fcntl(dbenv->lockfhp->fd, F_SETLK, &k_lock))
00106                         goto err;
00107 
00108                 /*
00109                  * If we got the resource lock we're done.
00110                  *
00111                  * !!!
00112                  * We can't check to see if the lock is ours, because we may
00113                  * be trying to block ourselves in the lock manager, and so
00114                  * the holder of the lock that's preventing us from getting
00115                  * the lock may be us!  (Seriously.)
00116                  */
00117                 if (locked)
00118                         break;
00119         }
00120 
00121 #ifdef DIAGNOSTIC
00122         /*
00123          * We want to switch threads as often as possible.  Yield every time
00124          * we get a mutex to ensure contention.
00125          */
00126         if (F_ISSET(dbenv, DB_ENV_YIELDCPU))
00127                 __os_yield(NULL, 1);
00128 #endif
00129         return (0);
00130 
00131 err:    ret = __os_get_errno();
00132         __db_err(dbenv, "fcntl lock failed: %s", db_strerror(ret));
00133         return (__db_panic(dbenv, ret));
00134 }
00135 
00136 /*
00137  * __db_fcntl_mutex_unlock --
00138  *      Release a mutex.
00139  *
00140  * PUBLIC: int __db_fcntl_mutex_unlock __P((DB_ENV *, db_mutex_t));
00141  */
00142 int
00143 __db_fcntl_mutex_unlock(dbenv, mutex)
00144         DB_ENV *dbenv;
00145         db_mutex_t mutex;
00146 {
00147         DB_MUTEX *mutexp;
00148         DB_MUTEXMGR *mtxmgr;
00149         DB_MUTEXREGION *mtxregion;
00150 
00151         if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00152                 return (0);
00153 
00154         mtxmgr = dbenv->mutex_handle;
00155         mtxregion = mtxmgr->reginfo.primary;
00156         mutexp = MUTEXP_SET(mutex);
00157 
00158 #ifdef DIAGNOSTIC
00159         if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00160                 __db_err(dbenv, "fcntl unlock failed: lock already unlocked");
00161                 return (__db_panic(dbenv, EACCES));
00162         }
00163 #endif
00164 
00165         /*
00166          * Release the resource.  We don't have to acquire any locks because
00167          * processes trying to acquire the lock are waiting for the flag to
00168          * go to 0.  Once that happens the waiters will serialize acquiring 
00169          * an exclusive kernel lock before locking the mutex.
00170          */
00171         F_CLR(mutexp, DB_MUTEX_LOCKED);
00172 
00173         return (0);
00174 }
00175 
00176 /*
00177  * __db_fcntl_mutex_destroy --
00178  *      Destroy a mutex.
00179  *
00180  * PUBLIC: int __db_fcntl_mutex_destroy __P((DB_ENV *, db_mutex_t));
00181  */
00182 int
00183 __db_fcntl_mutex_destroy(dbenv, mutex)
00184         DB_ENV *dbenv;
00185         db_mutex_t mutex;
00186 {
00187         COMPQUIET(dbenv, NULL);
00188         COMPQUIET(mutex, MUTEX_INVALID);
00189 
00190         return (0);
00191 }

Generated on Sun Dec 25 12:14:41 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2