source: trunk/third/rpm/db/mutex/mut_tas.c @ 19079

Revision 19079, 4.6 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19078, which included commits to RCS files with non-trunk default branches.
Line 
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996-2002
5 *      Sleepycat Software.  All rights reserved.
6 */
7
8#include "db_config.h"
9
10#ifndef lint
11static const char revid[] = "Id: mut_tas.c,v 11.32 2002/05/07 18:42:21 bostic Exp ";
12#endif /* not lint */
13
14#ifndef NO_SYSTEM_INCLUDES
15#include <sys/types.h>
16
17#include <stdlib.h>
18#include <string.h>
19#include <unistd.h>
20#endif
21
22/*
23 * This is where we load in the actual test-and-set mutex code.
24 */
25#define LOAD_ACTUAL_MUTEX_CODE
26#include "db_int.h"
27
28/*
29 * __db_tas_mutex_init --
30 *      Initialize a DB_MUTEX.
31 *
32 * PUBLIC: int __db_tas_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
33 */
34int
35__db_tas_mutex_init(dbenv, mutexp, flags)
36        DB_ENV *dbenv;
37        DB_MUTEX *mutexp;
38        u_int32_t flags;
39{
40        u_int32_t save;
41
42        /* Check alignment. */
43        DB_ASSERT(((db_alignp_t)mutexp & (MUTEX_ALIGN - 1)) == 0);
44
45        /*
46         * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
47         * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
48         * flag.  This is safe because even if this flag was never explicitly
49         * set, but happened to be set in memory, it will never be checked or
50         * acted upon.
51         */
52        save = F_ISSET(mutexp, MUTEX_MPOOL);
53        memset(mutexp, 0, sizeof(*mutexp));
54        F_SET(mutexp, save);
55
56        /*
57         * If this is a thread lock or the process has told us that there are
58         * no other processes in the environment, use thread-only locks, they
59         * are faster in some cases.
60         *
61         * This is where we decide to ignore locks we don't need to set -- if
62         * the application isn't threaded, there aren't any threads to block.
63         */
64        if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
65                if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
66                        F_SET(mutexp, MUTEX_IGNORE);
67                        return (0);
68                }
69        }
70
71        /* Initialize the lock. */
72        if (MUTEX_INIT(&mutexp->tas))
73                return (__os_get_errno());
74
75        mutexp->spins = __os_spin(dbenv);
76#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
77        mutexp->reg_off = INVALID_ROFF;
78#endif
79        F_SET(mutexp, MUTEX_INITED);
80
81        return (0);
82}
83
84/*
85 * __db_tas_mutex_lock
86 *      Lock on a mutex, logically blocking if necessary.
87 *
88 * PUBLIC: int __db_tas_mutex_lock __P((DB_ENV *, DB_MUTEX *));
89 */
90int
91__db_tas_mutex_lock(dbenv, mutexp)
92        DB_ENV *dbenv;
93        DB_MUTEX *mutexp;
94{
95        u_long ms;
96        int nspins;
97
98        if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
99                return (0);
100
101        ms = 1;
102
103loop:   /* Attempt to acquire the resource for N spins. */
104        for (nspins = mutexp->spins; nspins > 0; --nspins) {
105#ifdef HAVE_MUTEX_HPPA_MSEM_INIT
106relock:
107#endif
108                if (!MUTEX_SET(&mutexp->tas))
109                        continue;
110#ifdef HAVE_MUTEX_HPPA_MSEM_INIT
111                /*
112                 * HP semaphores are unlocked automatically when a holding
113                 * process exits.  If the mutex appears to be locked
114                 * (mutexp->locked != 0) but we got here, assume this has
115                 * happened.  Stick our own pid into mutexp->locked and
116                 * lock again.  (The default state of the mutexes used to
117                 * block in __lock_get_internal is locked, so exiting with
118                 * a locked mutex is reasonable behavior for a process that
119                 * happened to initialize or use one of them.)
120                 */
121                if (mutexp->locked != 0) {
122                        __os_id(&mutexp->locked);
123                        goto relock;
124                }
125                /*
126                 * If we make it here, locked == 0, the diagnostic won't fire,
127                 * and we were really unlocked by someone calling the
128                 * DB mutex unlock function.
129                 */
130#endif
131#ifdef DIAGNOSTIC
132                if (mutexp->locked != 0)
133                        __db_err(dbenv,
134                "__db_tas_mutex_lock: ERROR: lock currently in use: ID: %lu",
135                            (u_long)mutexp->locked);
136#endif
137#if defined(DIAGNOSTIC) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
138                __os_id(&mutexp->locked);
139#endif
140                if (ms == 1)
141                        ++mutexp->mutex_set_nowait;
142                else
143                        ++mutexp->mutex_set_wait;
144                return (0);
145        }
146
147        /* Yield the processor; wait 1ms initially, up to 1 second. */
148        __os_yield(NULL, ms * USEC_PER_MS);
149        if ((ms <<= 1) > MS_PER_SEC)
150                ms = MS_PER_SEC;
151
152        goto loop;
153}
154
155/*
156 * __db_tas_mutex_unlock --
157 *      Release a lock.
158 *
159 * PUBLIC: int __db_tas_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
160 */
161int
162__db_tas_mutex_unlock(dbenv, mutexp)
163        DB_ENV *dbenv;
164        DB_MUTEX *mutexp;
165{
166        if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
167                return (0);
168
169#ifdef DIAGNOSTIC
170        if (!mutexp->locked)
171                __db_err(dbenv,
172                    "__db_tas_mutex_unlock: ERROR: lock already unlocked");
173#endif
174#if defined(DIAGNOSTIC) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
175        mutexp->locked = 0;
176#endif
177
178        MUTEX_UNSET(&mutexp->tas);
179
180        return (0);
181}
182
183/*
184 * __db_tas_mutex_destroy --
185 *      Destroy a DB_MUTEX.
186 *
187 * PUBLIC: int __db_tas_mutex_destroy __P((DB_MUTEX *));
188 */
189int
190__db_tas_mutex_destroy(mutexp)
191        DB_MUTEX *mutexp;
192{
193        if (F_ISSET(mutexp, MUTEX_IGNORE))
194                return (0);
195
196        MUTEX_DESTROY(&mutexp->tas);
197
198        return (0);
199}
Note: See TracBrowser for help on using the repository browser.