mut_fcntl.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifdef HAVE_MUTEX_FCNTL
00011 
00012 #ifndef lint
00013 static const char revid[] = "$Id: mut__fcntl_8c-source.html,v 1.1 2008/06/08 10:20:55 sebdiaz Exp $";
00014 #endif /* not lint */
00015 
00016 #ifndef NO_SYSTEM_INCLUDES
00017 #include <sys/types.h>
00018 
00019 #include <errno.h>
00020 #include <fcntl.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #endif
00025 
00026 #include "db_int.h"
00027 
00028 /*
00029  * __db_fcntl_mutex_init --
00030  *      Initialize a DB mutex structure.
00031  *
00032  * PUBLIC: int __db_fcntl_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t));
00033  */
00034 int
00035 __db_fcntl_mutex_init(dbenv, mutexp, offset)
00036         DB_ENV *dbenv;
00037         MUTEX *mutexp;
00038         u_int32_t offset;
00039 {
00040         memset(mutexp, 0, sizeof(*mutexp));
00041 
00042         /*
00043          * This is where we decide to ignore locks we don't need to set -- if
00044          * the application is private, we don't need any locks.
00045          */
00046         if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00047                 F_SET(mutexp, MUTEX_IGNORE);
00048                 return (0);
00049         }
00050 
00051         mutexp->off = offset;
00052 
00053         return (0);
00054 }
00055 
00056 /*
00057  * __db_fcntl_mutex_lock
00058  *      Lock on a mutex, blocking if necessary.
00059  *
00060  * PUBLIC: int __db_fcntl_mutex_lock __P((MUTEX *, DB_FH *));
00061  */
00062 int
00063 __db_fcntl_mutex_lock(mutexp, fhp)
00064         MUTEX *mutexp;
00065         DB_FH *fhp;
00066 {
00067         struct flock k_lock;
00068         int locked, ms, waited;
00069 
00070         if (!DB_GLOBAL(db_mutexlocks))
00071                 return (0);
00072 
00073         /* Initialize the lock. */
00074         k_lock.l_whence = SEEK_SET;
00075         k_lock.l_start = mutexp->off;
00076         k_lock.l_len = 1;
00077 
00078         for (locked = waited = 0;;) {
00079                 /*
00080                  * Wait for the lock to become available; wait 1ms initially,
00081                  * up to 1 second.
00082                  */
00083                 for (ms = 1; mutexp->pid != 0;) {
00084                         waited = 1;
00085                         CDB___os_yield(NULL, ms * USEC_PER_MS);
00086                         if ((ms <<= 1) > MS_PER_SEC)
00087                                 ms = MS_PER_SEC;
00088                 }
00089 
00090                 /* Acquire an exclusive kernel lock. */
00091                 k_lock.l_type = F_WRLCK;
00092                 if (fcntl(fhp->fd, F_SETLKW, &k_lock))
00093                         return (CDB___os_get_errno());
00094 
00095                 /* If the resource is still available, it's ours. */
00096                 if (mutexp->pid == 0) {
00097                         locked = 1;
00098                         mutexp->pid = (u_int32_t)getpid();
00099                 }
00100 
00101                 /* Release the kernel lock. */
00102                 k_lock.l_type = F_UNLCK;
00103                 if (fcntl(fhp->fd, F_SETLK, &k_lock))
00104                         return (CDB___os_get_errno());
00105 
00106                 /*
00107                  * If we got the resource lock we're done.
00108                  *
00109                  * !!!
00110                  * We can't check to see if the lock is ours, because we may
00111                  * be trying to block ourselves in the lock manager, and so
00112                  * the holder of the lock that's preventing us from getting
00113                  * the lock may be us!  (Seriously.)
00114                  */
00115                 if (locked)
00116                         break;
00117         }
00118 
00119         if (waited)
00120                 ++mutexp->mutex_set_wait;
00121         else
00122                 ++mutexp->mutex_set_nowait;
00123         return (0);
00124 }
00125 
00126 /*
00127  * __db_fcntl_mutex_unlock --
00128  *      Release a lock.
00129  *
00130  * PUBLIC: int __db_fcntl_mutex_unlock __P((MUTEX *));
00131  */
00132 int
00133 __db_fcntl_mutex_unlock(mutexp)
00134         MUTEX *mutexp;
00135 {
00136         if (!DB_GLOBAL(db_mutexlocks))
00137                 return (0);
00138 
00139 #ifdef DIAGNOSTIC
00140 #define MSG             "mutex_unlock: ERROR: released lock that was unlocked\n"
00141 #ifndef STDERR_FILENO
00142 #define STDERR_FILENO   2
00143 #endif
00144         if (mutexp->pid == 0)
00145                 write(STDERR_FILENO, MSG, sizeof(MSG) - 1);
00146 #endif
00147 
00148         /*
00149          * Release the resource.  We don't have to acquire any locks because
00150          * processes trying to acquire the lock are checking for a pid set to
00151          * 0/non-0, not to any specific value.
00152          */
00153         mutexp->pid = 0;
00154 
00155         return (0);
00156 }
00157 
00158 #endif /* HAVE_MUTEX_FCNTL */

Generated on Sun Jun 8 10:56:38 2008 for GNUmifluz by  doxygen 1.5.5