Remove definition of builtin function
[platform/upstream/db4.git] / mutex / mut_region.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996-2009 Oracle.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12 #include "dbinc/log.h"
13 #include "dbinc/lock.h"
14 #include "dbinc/mp.h"
15 #include "dbinc/txn.h"
16
17 static size_t __mutex_align_size __P((ENV *));
18 static int __mutex_region_init __P((ENV *, DB_MUTEXMGR *));
19 static size_t __mutex_region_size __P((ENV *));
20
21 /*
22  * __mutex_open --
23  *      Open a mutex region.
24  *
25  * PUBLIC: int __mutex_open __P((ENV *, int));
26  */
27 int
28 __mutex_open(env, create_ok)
29         ENV *env;
30         int create_ok;
31 {
32         DB_ENV *dbenv;
33         DB_MUTEXMGR *mtxmgr;
34         DB_MUTEXREGION *mtxregion;
35         db_mutex_t mutex;
36         u_int32_t cpu_count;
37         u_int i;
38         int ret;
39
40         dbenv = env->dbenv;
41
42         /*
43          * Initialize the ENV handle information if not already initialized.
44          *
45          * Align mutexes on the byte boundaries specified by the application.
46          */
47         if (dbenv->mutex_align == 0)
48                 dbenv->mutex_align = MUTEX_ALIGN;
49         if (dbenv->mutex_tas_spins == 0) {
50                 cpu_count = __os_cpu_count();
51                 if ((ret = __mutex_set_tas_spins(dbenv, cpu_count == 1 ?
52                     cpu_count : cpu_count * MUTEX_SPINS_PER_PROCESSOR)) != 0)
53                         return (ret);
54         }
55
56         /*
57          * If the user didn't set an absolute value on the number of mutexes
58          * we'll need, figure it out.  We're conservative in our allocation,
59          * we need mutexes for DB handles, group-commit queues and other things
60          * applications allocate at run-time.  The application may have kicked
61          * up our count to allocate its own mutexes, add that in.
62          */
63         if (dbenv->mutex_cnt == 0)
64                 dbenv->mutex_cnt =
65                     __lock_region_mutex_count(env) +
66                     __log_region_mutex_count(env) +
67                     __memp_region_mutex_count(env) +
68                     __txn_region_mutex_count(env) +
69                     dbenv->mutex_inc + 100;
70
71         /* Create/initialize the mutex manager structure. */
72         if ((ret = __os_calloc(env, 1, sizeof(DB_MUTEXMGR), &mtxmgr)) != 0)
73                 return (ret);
74
75         /* Join/create the mutex region. */
76         mtxmgr->reginfo.env = env;
77         mtxmgr->reginfo.type = REGION_TYPE_MUTEX;
78         mtxmgr->reginfo.id = INVALID_REGION_ID;
79         mtxmgr->reginfo.flags = REGION_JOIN_OK;
80         if (create_ok)
81                 F_SET(&mtxmgr->reginfo, REGION_CREATE_OK);
82         if ((ret = __env_region_attach(env,
83             &mtxmgr->reginfo, __mutex_region_size(env))) != 0)
84                 goto err;
85
86         /* If we created the region, initialize it. */
87         if (F_ISSET(&mtxmgr->reginfo, REGION_CREATE))
88                 if ((ret = __mutex_region_init(env, mtxmgr)) != 0)
89                         goto err;
90
91         /* Set the local addresses. */
92         mtxregion = mtxmgr->reginfo.primary =
93             R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary);
94         mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_off);
95
96         env->mutex_handle = mtxmgr;
97
98         /* Allocate initial queue of mutexes. */
99         if (env->mutex_iq != NULL) {
100                 DB_ASSERT(env, F_ISSET(&mtxmgr->reginfo, REGION_CREATE));
101                 for (i = 0; i < env->mutex_iq_next; ++i) {
102                         if ((ret = __mutex_alloc_int(
103                             env, 0, env->mutex_iq[i].alloc_id,
104                             env->mutex_iq[i].flags, &mutex)) != 0)
105                                 goto err;
106                         /*
107                          * Confirm we allocated the right index, correcting
108                          * for avoiding slot 0 (MUTEX_INVALID).
109                          */
110                         DB_ASSERT(env, mutex == i + 1);
111                 }
112                 __os_free(env, env->mutex_iq);
113                 env->mutex_iq = NULL;
114 #ifndef HAVE_ATOMIC_SUPPORT
115                 /* If necessary allocate the atomic emulation mutexes.  */
116                 for (i = 0; i != MAX_ATOMIC_MUTEXES; i++)
117                         if ((ret = __mutex_alloc_int(
118                             env, 0, MTX_ATOMIC_EMULATION,
119                             0, &mtxregion->mtx_atomic[i])) != 0)
120                                 return (ret);
121 #endif
122
123                 /*
124                  * This is the first place we can test mutexes and we need to
125                  * know if they're working.  (They CAN fail, for example on
126                  * SunOS, when using fcntl(2) for locking and using an
127                  * in-memory filesystem as the database environment directory.
128                  * But you knew that, I'm sure -- it probably wasn't worth
129                  * mentioning.)
130                  */
131                 mutex = MUTEX_INVALID;
132                 if ((ret =
133                     __mutex_alloc(env, MTX_MUTEX_TEST, 0, &mutex) != 0) ||
134                     (ret = __mutex_lock(env, mutex)) != 0 ||
135                     (ret = __mutex_unlock(env, mutex)) != 0 ||
136                     (ret = __mutex_trylock(env, mutex)) != 0 ||
137                     (ret = __mutex_unlock(env, mutex)) != 0 ||
138                     (ret = __mutex_free(env, &mutex)) != 0) {
139                         __db_errx(env,
140                     "Unable to acquire/release a mutex; check configuration");
141                         goto err;
142                 }
143 #ifdef HAVE_SHARED_LATCHES
144                 if ((ret =
145                     __mutex_alloc(env,
146                         MTX_MUTEX_TEST, DB_MUTEX_SHARED, &mutex) != 0) ||
147                     (ret = __mutex_lock(env, mutex)) != 0 ||
148                     (ret = __mutex_unlock(env, mutex)) != 0 ||
149                     (ret = __mutex_rdlock(env, mutex)) != 0 ||
150                     (ret = __mutex_rdlock(env, mutex)) != 0 ||
151                     (ret = __mutex_unlock(env, mutex)) != 0 ||
152                     (ret = __mutex_unlock(env, mutex)) != 0 ||
153                     (ret = __mutex_free(env, &mutex)) != 0) {
154                         __db_errx(env,
155             "Unable to acquire/release a shared latch; check configuration");
156                         goto err;
157                 }
158 #endif
159         }
160         return (0);
161
162 err:    env->mutex_handle = NULL;
163         if (mtxmgr->reginfo.addr != NULL)
164                 (void)__env_region_detach(env, &mtxmgr->reginfo, 0);
165
166         __os_free(env, mtxmgr);
167         return (ret);
168 }
169
170 /*
171  * __mutex_region_init --
172  *      Initialize a mutex region in shared memory.
173  */
174 static int
175 __mutex_region_init(env, mtxmgr)
176         ENV *env;
177         DB_MUTEXMGR *mtxmgr;
178 {
179         DB_ENV *dbenv;
180         DB_MUTEX *mutexp;
181         DB_MUTEXREGION *mtxregion;
182         db_mutex_t i;
183         int ret;
184         void *mutex_array;
185
186         dbenv = env->dbenv;
187
188         COMPQUIET(mutexp, NULL);
189
190         if ((ret = __env_alloc(&mtxmgr->reginfo,
191             sizeof(DB_MUTEXREGION), &mtxmgr->reginfo.primary)) != 0) {
192                 __db_errx(env,
193                     "Unable to allocate memory for the mutex region");
194                 return (ret);
195         }
196         mtxmgr->reginfo.rp->primary =
197             R_OFFSET(&mtxmgr->reginfo, mtxmgr->reginfo.primary);
198         mtxregion = mtxmgr->reginfo.primary;
199         memset(mtxregion, 0, sizeof(*mtxregion));
200
201         if ((ret = __mutex_alloc(
202             env, MTX_MUTEX_REGION, 0, &mtxregion->mtx_region)) != 0)
203                 return (ret);
204         mtxmgr->reginfo.mtx_alloc = mtxregion->mtx_region;
205
206         mtxregion->mutex_size = __mutex_align_size(env);
207
208         mtxregion->stat.st_mutex_align = dbenv->mutex_align;
209         mtxregion->stat.st_mutex_cnt = dbenv->mutex_cnt;
210         mtxregion->stat.st_mutex_tas_spins = dbenv->mutex_tas_spins;
211
212         /*
213          * Get a chunk of memory to be used for the mutexes themselves.  Each
214          * piece of the memory must be properly aligned, and that alignment
215          * may be more restrictive than the memory alignment returned by the
216          * underlying allocation code.  We already know how much memory each
217          * mutex in the array will take up, but we need to offset the first
218          * mutex in the array so the array begins properly aligned.
219          *
220          * The OOB mutex (MUTEX_INVALID) is 0.  To make this work, we ignore
221          * the first allocated slot when we build the free list.  We have to
222          * correct the count by 1 here, though, otherwise our counter will be
223          * off by 1.
224          */
225         if ((ret = __env_alloc(&mtxmgr->reginfo,
226             mtxregion->stat.st_mutex_align +
227             (mtxregion->stat.st_mutex_cnt + 1) * mtxregion->mutex_size,
228             &mutex_array)) != 0) {
229                 __db_errx(env,
230                     "Unable to allocate memory for mutexes from the region");
231                 return (ret);
232         }
233
234         mtxregion->mutex_off_alloc = R_OFFSET(&mtxmgr->reginfo, mutex_array);
235         mutex_array = ALIGNP_INC(mutex_array, mtxregion->stat.st_mutex_align);
236         mtxregion->mutex_off = R_OFFSET(&mtxmgr->reginfo, mutex_array);
237         mtxmgr->mutex_array = mutex_array;
238
239         /*
240          * Put the mutexes on a free list and clear the allocated flag.
241          *
242          * The OOB mutex (MUTEX_INVALID) is 0, skip it.
243          *
244          * The comparison is <, not <=, because we're looking ahead one
245          * in each link.
246          */
247         for (i = 1; i < mtxregion->stat.st_mutex_cnt; ++i) {
248                 mutexp = MUTEXP_SET(mtxmgr, i);
249                 mutexp->flags = 0;
250                 mutexp->mutex_next_link = i + 1;
251         }
252         mutexp = MUTEXP_SET(mtxmgr, i);
253         mutexp->flags = 0;
254         mutexp->mutex_next_link = MUTEX_INVALID;
255         mtxregion->mutex_next = 1;
256         mtxregion->stat.st_mutex_free = mtxregion->stat.st_mutex_cnt;
257         mtxregion->stat.st_mutex_inuse = mtxregion->stat.st_mutex_inuse_max = 0;
258
259         return (0);
260 }
261
262 /*
263  * __mutex_env_refresh --
264  *      Clean up after the mutex region on a close or failed open.
265  *
266  * PUBLIC: int __mutex_env_refresh __P((ENV *));
267  */
268 int
269 __mutex_env_refresh(env)
270         ENV *env;
271 {
272         DB_MUTEXMGR *mtxmgr;
273         DB_MUTEXREGION *mtxregion;
274         REGINFO *reginfo;
275         int ret;
276
277         mtxmgr = env->mutex_handle;
278         reginfo = &mtxmgr->reginfo;
279         mtxregion = mtxmgr->reginfo.primary;
280
281         /*
282          * If a private region, return the memory to the heap.  Not needed for
283          * filesystem-backed or system shared memory regions, that memory isn't
284          * owned by any particular process.
285          */
286         if (F_ISSET(env, ENV_PRIVATE)) {
287                 reginfo->mtx_alloc = MUTEX_INVALID;
288
289 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
290                 /*
291                  * If destroying the mutex region, return any system resources
292                  * to the system.
293                  */
294                 __mutex_resource_return(env, reginfo);
295 #endif
296                 /* Discard the mutex array. */
297                 __env_alloc_free(
298                     reginfo, R_ADDR(reginfo, mtxregion->mutex_off_alloc));
299         }
300
301         /* Detach from the region. */
302         ret = __env_region_detach(env, reginfo, 0);
303
304         __os_free(env, mtxmgr);
305
306         env->mutex_handle = NULL;
307
308         return (ret);
309 }
310
311 /*
312  * __mutex_align_size --
313  *      Return how much memory each mutex will take up if an array of them
314  *      are to be properly aligned, individually, within the array.
315  */
316 static size_t
317 __mutex_align_size(env)
318         ENV *env;
319 {
320         DB_ENV *dbenv;
321
322         dbenv = env->dbenv;
323
324         return ((size_t)DB_ALIGN(sizeof(DB_MUTEX), dbenv->mutex_align));
325 }
326
327 /*
328  * __mutex_region_size --
329  *       Return the amount of space needed for the mutex region.
330  */
331 static size_t
332 __mutex_region_size(env)
333         ENV *env;
334 {
335         DB_ENV *dbenv;
336         size_t s;
337
338         dbenv = env->dbenv;
339
340         s = sizeof(DB_MUTEXMGR) + 1024;
341
342         /* We discard one mutex for the OOB slot. */
343         s += __env_alloc_size(
344             (dbenv->mutex_cnt + 1) *__mutex_align_size(env));
345
346         return (s);
347 }
348
349 #ifdef  HAVE_MUTEX_SYSTEM_RESOURCES
350 /*
351  * __mutex_resource_return
352  *      Return any system-allocated mutex resources to the system.
353  *
354  * PUBLIC: void __mutex_resource_return __P((ENV *, REGINFO *));
355  */
356 void
357 __mutex_resource_return(env, infop)
358         ENV *env;
359         REGINFO *infop;
360 {
361         DB_MUTEX *mutexp;
362         DB_MUTEXMGR *mtxmgr, mtxmgr_st;
363         DB_MUTEXREGION *mtxregion;
364         db_mutex_t i;
365         void *orig_handle;
366
367         /*
368          * This routine is called in two cases: when discarding the regions
369          * from a previous Berkeley DB run, during recovery, and two, when
370          * discarding regions as we shut down the database environment.
371          *
372          * Walk the list of mutexes and destroy any live ones.
373          *
374          * This is just like joining a region -- the REGINFO we're handed is
375          * the same as the one returned by __env_region_attach(), all we have
376          * to do is fill in the links.
377          *
378          * !!!
379          * The region may be corrupted, of course.  We're safe because the
380          * only things we look at are things that are initialized when the
381          * region is created, and never modified after that.
382          */
383         memset(&mtxmgr_st, 0, sizeof(mtxmgr_st));
384         mtxmgr = &mtxmgr_st;
385         mtxmgr->reginfo = *infop;
386         mtxregion = mtxmgr->reginfo.primary =
387             R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary);
388         mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_off);
389
390         /*
391          * This is a little strange, but the mutex_handle is what all of the
392          * underlying mutex routines will use to determine if they should do
393          * any work and to find their information.  Save/restore the handle
394          * around the work loop.
395          *
396          * The OOB mutex (MUTEX_INVALID) is 0, skip it.
397          */
398         orig_handle = env->mutex_handle;
399         env->mutex_handle = mtxmgr;
400         for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
401                 mutexp = MUTEXP_SET(mtxmgr, i);
402                 if (F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
403                         (void)__mutex_destroy(env, i);
404         }
405         env->mutex_handle = orig_handle;
406 }
407 #endif