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

os_region.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: os_region.c,v 12.4 2005/07/21 01:36:18 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <string.h>
00016 #endif
00017 
00018 #include "db_int.h"
00019 
00020 /*
00021  * __os_r_attach --
00022  *      Attach to a shared memory region.
00023  *
00024  * PUBLIC: int __os_r_attach __P((DB_ENV *, REGINFO *, REGION *));
00025  */
00026 int
00027 __os_r_attach(dbenv, infop, rp)
00028         DB_ENV *dbenv;
00029         REGINFO *infop;
00030         REGION *rp;
00031 {
00032         int ret;
00033 
00034         /*
00035          * All regions are created on 8K boundaries out of sheer paranoia,
00036          * so we don't make some underlying VM unhappy. Make sure we don't
00037          * overflow or underflow.
00038          */
00039 #define OS_VMPAGESIZE           (8 * 1024)
00040 #define OS_VMROUNDOFF(i) {                                              \
00041         if ((i) <                                                       \
00042             (UINT32_MAX - OS_VMPAGESIZE) + 1 || (i) < OS_VMPAGESIZE)    \
00043                 (i) += OS_VMPAGESIZE - 1;                               \
00044         (i) -= (i) % OS_VMPAGESIZE;                                     \
00045 }
00046         OS_VMROUNDOFF(rp->size);
00047 
00048 #ifdef DB_REGIONSIZE_MAX
00049         /* Some architectures have hard limits on the maximum region size. */
00050         if (rp->size > DB_REGIONSIZE_MAX) {
00051                 __db_err(dbenv, "region size %lu is too large; maximum is %lu",
00052                     (u_long)rp->size, (u_long)DB_REGIONSIZE_MAX);
00053                 return (EINVAL);
00054         }
00055 #endif
00056 
00057         /*
00058          * If a region is private, malloc the memory.
00059          *
00060          * !!!
00061          * If this fails because the region is too large to malloc, mmap(2)
00062          * using the MAP_ANON or MAP_ANONYMOUS flags would be an alternative.
00063          * I don't know of any architectures (yet!) where malloc is a problem.
00064          */
00065         if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00066 #if defined(HAVE_MUTEX_HPPA_MSEM_INIT)
00067                 /*
00068                  * !!!
00069                  * There exist spinlocks that don't work in malloc memory, e.g.,
00070                  * the HP/UX msemaphore interface.  If we don't have locks that
00071                  * will work in malloc memory, we better not be private or not
00072                  * be threaded.
00073                  */
00074                 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00075                         __db_err(dbenv, "%s",
00076     "architecture does not support locks inside process-local (malloc) memory");
00077                         __db_err(dbenv, "%s",
00078     "application may not specify both DB_PRIVATE and DB_THREAD");
00079                         return (EINVAL);
00080                 }
00081 #endif
00082                 if ((ret = __os_malloc(
00083                     dbenv, sizeof(REGENV), &infop->addr)) != 0)
00084                         return (ret);
00085 
00086                 infop->max_alloc = rp->size;
00087         } else {
00088                 /*
00089                  * If the user replaced the map call, call through their
00090                  * interface.
00091                  */
00092                 if (DB_GLOBAL(j_map) != NULL && (ret = DB_GLOBAL(j_map)
00093                     (infop->name, rp->size, 1, 0, &infop->addr)) != 0)
00094                         return (ret);
00095 
00096                 /* Get some space from the underlying system. */
00097                 if ((ret = __os_r_sysattach(dbenv, infop, rp)) != 0)
00098                         return (ret);
00099         }
00100 
00101         /*
00102          * We may require alignment the underlying system or heap allocation
00103          * library doesn't supply.  Align the address if necessary, saving
00104          * the original values for restoration when the region is discarded.
00105          */
00106         infop->addr_orig = infop->addr;
00107         infop->addr = ALIGNP_INC(infop->addr_orig, sizeof(size_t));
00108 
00109         rp->size_orig = rp->size;
00110         if (infop->addr != infop->addr_orig)
00111                 rp->size -=
00112                     (u_int8_t *)infop->addr - (u_int8_t *)infop->addr_orig;
00113 
00114         return (0);
00115 }
00116 
00117 /*
00118  * __os_r_detach --
00119  *      Detach from a shared memory region.
00120  *
00121  * PUBLIC: int __os_r_detach __P((DB_ENV *, REGINFO *, int));
00122  */
00123 int
00124 __os_r_detach(dbenv, infop, destroy)
00125         DB_ENV *dbenv;
00126         REGINFO *infop;
00127         int destroy;
00128 {
00129         REGION *rp;
00130 
00131         rp = infop->rp;
00132 
00133         /* Restore any address/size altered for alignment reasons. */
00134         if (infop->addr != infop->addr_orig) {
00135                 infop->addr = infop->addr_orig;
00136                 rp->size = rp->size_orig;
00137         }
00138 
00139         /* If a region is private, free the memory. */
00140         if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00141                 __os_free(dbenv, infop->addr);
00142                 return (0);
00143         }
00144 
00145         /* If the user replaced the map call, call through their interface. */
00146         if (DB_GLOBAL(j_unmap) != NULL)
00147                 return (DB_GLOBAL(j_unmap)(infop->addr, rp->size));
00148 
00149         return (__os_r_sysdetach(dbenv, infop, destroy));
00150 }

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