diff options
author | Ulrich Drepper <drepper@redhat.com> | 1998-06-09 15:16:55 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1998-06-09 15:16:55 +0000 |
commit | bf7997b65c7887d2acda95f5201d818a19d81711 (patch) | |
tree | da3583de3a0b5892f90a4b1eb773a87b554ae37e /db2/os/os_map.c | |
parent | 7646e67e6cc4c738a7b402c60fed39d52db0433b (diff) | |
download | glibc-bf7997b65c7887d2acda95f5201d818a19d81711.tar.gz glibc-bf7997b65c7887d2acda95f5201d818a19d81711.tar.xz glibc-bf7997b65c7887d2acda95f5201d818a19d81711.zip |
Update.
1998-06-09 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/sysv/linux/netinet/ip.h (struct ip_options): Define __data member only for gcc. Reported by ak@muc.de. * misc/mntent.h: Undo last patch. * sysdeps/unix/sysv/linux/fstatvfs.c (fstatvfs): Undo last patch. * misc/tst/mntent.c: Adjust code for this change. * io/fts.c: Updated from a slightly more recent BSD version. * io/fts.h: Likewise. * libc.map: Add __libc_stack_end. * db2/Makefile (routines): Add lock_region. * db2/config.h: Update from db-2.4.14. * db2/db.h: Likewise. * db2/db_185.h: Likewise. * db2/db_int.h: Likewise. * db2/bt_close.c: Likewise. * db2/bt_compare.c: Likewise. * db2/bt_conv.c: Likewise. * db2/bt_cursor.c: Likewise. * db2/bt_delete.c: Likewise. * db2/bt_open.c: Likewise. * db2/bt_page.c: Likewise. * db2/bt_put.c: Likewise. * db2/bt_rec.c: Likewise. * db2/bt_recno.c: Likewise. * db2/bt_rsearch.c: Likewise. * db2/bt_search.c: Likewise. * db2/bt_split.c: Likewise. * db2/bt_stat.c: Likewise. * db2/btree.src: Likewise. * db2/btree_auto.c: Likewise. * db2/getlong.c: Likewise. * db2/db_appinit.c: Likewise. * db2/db_apprec.c: Likewise. * db2/db_byteorder.c: Likewise. * db2/db_err.c: Likewise. * db2/db_log2.c: Likewise. * db2/db_region.c: Likewise. * db2/db_salloc.c: Likewise. * db2/db_shash.c: Likewise. * db2/db.c: Likewise. * db2/db.src: Likewise. * db2/db_auto.c: Likewise. * db2/db_conv.c: Likewise. * db2/db_dispatch.c: Likewise. * db2/db_dup.c: Likewise. * db2/db_overflow.c: Likewise. * db2/db_pr.c: Likewise. * db2/db_rec.c: Likewise. * db2/db_ret.c: Likewise. * db2/db_thread.c: Likewise. * db2/db185.c: Likewise. * db2/db185_int.h: Likewise. * db2/dbm.c: Likewise. * db2/hash.c: Likewise. * db2/hash.src: Likewise. * db2/hash_auto.c: Likewise. * db2/hash_conv.c: Likewise. * db2/hash_debug.c: Likewise. * db2/hash_dup.c: Likewise. * db2/hash_func.c: Likewise. * db2/hash_page.c: Likewise. * db2/hash_rec.c: Likewise. * db2/hash_stat.c: Likewise. * db2/btree.h: Likewise. * db2/btree_ext.h: Likewise. * db2/clib_ext.h: Likewise. * db2/common_ext.h: Likewise. * db2/cxx_int.h: Likewise. * db2/db.h.src: Likewise. * db2/db_185.h.src: Likewise. * db2/db_am.h: Likewise. * db2/db_auto.h: Likewise. * db2/db_cxx.h: Likewise. * db2/db_dispatch.h: Likewise. * db2/db_ext.h: Likewise. * db2/db_int.h.src: Likewise. * db2/db_page.h: Likewise. * db2/db_shash.h: Likewise. * db2/db_swap.h: Likewise. * db2/hash.h: Likewise. * db2/hash_ext.h: Likewise. * db2/lock.h: Likewise. * db2/lock_ext.h: Likewise. * db2/log.h: Likewise. * db2/log_ext.h: Likewise. * db2/mp.h: Likewise. * db2/mp_ext.h: Likewise. * db2/mutex_ext.h: Likewise. * db2/os_ext.h: Likewise. * db2/os_func.h: Likewise. * db2/queue.h: Likewise. * db2/shqueue.h: Likewise. * db2/txn.h: Likewise. * db2/lock.c: Likewise. * db2/lock_conflict.c: Likewise. * db2/lock_deadlock.c: Likewise. * db2/lock_region.c: Likewise. * db2/lock_util.c: Likewise. * db2/log.c: Likewise. * db2/log.src: Likewise. * db2/log_archive.c: Likewise. * db2/log_auto.c: Likewise. * db2/log_compare.c: Likewise. * db2/log_findckp.c: Likewise. * db2/log_get.c: Likewise. * db2/log_put.c: Likewise. * db2/log_rec.c: Likewise. * db2/log_register.c: Likewise. * db2/mp_bh.c: Likewise. * db2/mp_fget.c: Likewise. * db2/mp_fopen.c: Likewise. * db2/mp_fput.c: Likewise. * db2/mp_fset.c: Likewise. * db2/mp_open.c: Likewise. * db2/mp_pr.c: Likewise. * db2/mp_region.c: Likewise. * db2/mp_sync.c: Likewise. * db2/68020.gcc: Likewise. * db2/mutex.c: Likewise. * db2/parisc.gcc: Likewise. * db2/parisc.hp: Likewise. * db2/sco.cc: Likewise. * db2/os_abs.c: Likewise. * db2/os_alloc.c: Likewise. * db2/os_config.c: Likewise. * db2/os_dir.c: Likewise. * db2/os_fid.c: Likewise. * db2/os_fsync.c: Likewise. * db2/os_map.c: Likewise. * db2/os_oflags.c: Likewise. * db2/os_open.c: Likewise. * db2/os_rpath.c: Likewise. * db2/os_rw.c: Likewise. * db2/os_seek.c: Likewise. * db2/os_sleep.c: Likewise. * db2/os_spin.c: Likewise. * db2/os_stat.c: Likewise. * db2/os_unlink.c: Likewise. * db2/db_archive.c: Likewise. * db2/db_checkpoint.c: Likewise. * db2/db_deadlock.c: Likewise. * db2/db_dump.c: Likewise. * db2/db_dump185.c: Likewise. * db2/db_load.c: Likewise. * db2/db_printlog.c: Likewise. * db2/db_recover.c: Likewise. * db2/db_stat.c: Likewise. * db2/txn.c: Likewise. * db2/txn.src: Likewise. * db2/txn_auto.c: Likewise. * db2/txn_rec.c: Likewise. * elf/rtld.c: Move definition of __libc_stack_end to ... * sysdeps/generic/dl-sysdep.h: ...here. * sysdeps/unix/sysv/linux/fstatvfs.c: Handle nodiratime option. * sysdeps/unix/sysv/linux/bits/statvfs.h: Define ST_NODIRATIME. * sysdeps/unix/sysv/linux/sys/mount.h: Define MS_NODIRATIME. 1998-06-08 21:44 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/sysv/linux/fstatvfs.c: Handle constant option string from mntent correctly. 1998-06-06 Andreas Jaeger <aj@arthur.rhein-neckar.de> * sunrpc/Makefile (generated): Correct typo. 1998-06-04 Philip Blundell <philb@gnu.org> * elf/elf.h (EM_ARM, et al.): New definitions. * sysdeps/arm/dl-machine.h: Update for new draft ARM ELF ABI.
Diffstat (limited to 'db2/os/os_map.c')
-rw-r--r-- | db2/os/os_map.c | 440 |
1 files changed, 417 insertions, 23 deletions
diff --git a/db2/os/os_map.c b/db2/os/os_map.c index b1553188dc..5f0fd790e6 100644 --- a/db2/os/os_map.c +++ b/db2/os/os_map.c @@ -1,47 +1,395 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 1997 + * Copyright (c) 1996, 1997, 1998 * Sleepycat Software. All rights reserved. */ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)os_map.c 10.7 (Sleepycat) 10/25/97"; +static const char sccsid[] = "@(#)os_map.c 10.19 (Sleepycat) 5/3/98"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES #include <sys/types.h> +#ifdef HAVE_MMAP #include <sys/mman.h> +#endif + +#ifdef HAVE_SHMGET +#include <sys/ipc.h> +#include <sys/shm.h> +#endif #include <errno.h> +#include <string.h> #endif #include "db_int.h" +#include "common_ext.h" + +#ifdef HAVE_MMAP +static int __os_map __P((char *, int, size_t, int, int, int, void **)); +#endif +#ifdef HAVE_SHMGET +static int __os_shmget __P((char *, REGINFO *)); +#endif /* - * __os_map -- - * Map in some shared memory backed by a file descriptor. + * __db_mapanon_ok -- + * Return if this OS can support anonymous memory regions. + * + * PUBLIC: int __db_mapanon_ok __P((int)); + */ +int +__db_mapanon_ok(need_names) + int need_names; +{ + int ret; + + ret = EINVAL; + + /* + * If we don't have spinlocks, we have to have a file descriptor + * for fcntl(2) locking, which implies using mmap(2) to map in a + * regular file. Theoretically, we could probably find ways to + * get a file descriptor to lock other types of shared regions, + * but I don't see any reason to do so. + * + * If need_names is set, the application wants to share anonymous + * memory among multiple processes, so we have to have a way to + * name it. This requires shmget(2), on UNIX systems. + */ +#ifdef HAVE_SPINLOCKS +#ifdef HAVE_SHMGET + ret = 0; +#endif +#ifdef HAVE_MMAP +#ifdef MAP_ANON + if (!need_names) + ret = 0; +#endif +#ifdef MAP_ANONYMOUS + if (!need_names) + ret = 0; +#endif +#else + COMPQUIET(need_names, 0); +#endif /* HAVE_MMAP */ +#endif /* HAVE_SPINLOCKS */ + + return (ret); +} + +/* + * __db_mapinit -- + * Return if shared regions need to be initialized. + * + * PUBLIC: int __db_mapinit __P((void)); + */ +int +__db_mapinit() +{ + /* + * Historically, some systems required that all of the bytes of the + * region be written before it could be mmapped and accessed randomly. + * We have the option of setting REGION_INIT_NEEDED at configuration + * time if we're running on one of those systems. + */ +#ifdef REGION_INIT_NEEDED + return (1); +#else + return (0); +#endif +} + +/* + * __db_mapregion -- + * Attach to a shared memory region. + * + * PUBLIC: int __db_mapregion __P((char *, REGINFO *)); + */ +int +__db_mapregion(path, infop) + char *path; + REGINFO *infop; +{ + int called, ret; + + called = 0; + ret = EINVAL; + + /* If the user replaces the map call, call through their interface. */ + if (__db_jump.j_map != NULL) { + F_SET(infop, REGION_HOLDINGSYS); + return (__db_jump.j_map(path, infop->fd, infop->size, + 1, F_ISSET(infop, REGION_ANONYMOUS), 0, &infop->addr)); + } + + if (F_ISSET(infop, REGION_ANONYMOUS)) { + /* + * !!! + * If we're creating anonymous regions: + * + * If it's private, we use mmap(2). The problem with using + * shmget(2) is that we may be creating a region of which the + * application isn't aware, and if the application crashes + * we'll have no way to remove the system resources for the + * region. + * + * If it's not private, we use the shmget(2) interface if it's + * available, because it allows us to name anonymous memory. + * If shmget(2) isn't available, use the mmap(2) calls. + * + * In the case of anonymous memory, using mmap(2) means the + * memory isn't named and only the single process and its + * threads can access the region. + */ +#ifdef HAVE_MMAP +#ifdef MAP_ANON +#define HAVE_MMAP_ANONYMOUS 1 +#else +#ifdef MAP_ANONYMOUS +#define HAVE_MMAP_ANONYMOUS 1 +#endif +#endif +#endif +#ifdef HAVE_MMAP_ANONYMOUS + if (!called && F_ISSET(infop, REGION_PRIVATE)) { + called = 1; + ret = __os_map(path, + infop->fd, infop->size, 1, 1, 0, &infop->addr); + } +#endif +#ifdef HAVE_SHMGET + if (!called) { + called = 1; + ret = __os_shmget(path, infop); + } +#endif +#ifdef HAVE_MMAP + /* + * If we're trying to join an unnamed anonymous region, fail -- + * that's not possible. + */ + if (!called) { + called = 1; + + if (!F_ISSET(infop, REGION_CREATED)) { + __db_err(infop->dbenv, + "cannot join region in unnamed anonymous memory"); + return (EINVAL); + } + + ret = __os_map(path, + infop->fd, infop->size, 1, 1, 0, &infop->addr); + } +#endif + } else { + /* + * !!! + * If we're creating normal regions, we use the mmap(2) + * interface if it's available because it's POSIX 1003.1 + * standard and we trust it more than we do shmget(2). + */ +#ifdef HAVE_MMAP + if (!called) { + called = 1; + + /* Mmap(2) regions that aren't anonymous can grow. */ + F_SET(infop, REGION_CANGROW); + + ret = __os_map(path, + infop->fd, infop->size, 1, 0, 0, &infop->addr); + } +#endif +#ifdef HAVE_SHMGET + if (!called) { + called = 1; + ret = __os_shmget(path, infop); + } +#endif + } + return (ret); +} + +/* + * __db_unmapregion -- + * Detach from the shared memory region. + * + * PUBLIC: int __db_unmapregion __P((REGINFO *)); + */ +int +__db_unmapregion(infop) + REGINFO *infop; +{ + int called, ret; + + called = 0; + ret = EINVAL; + + if (__db_jump.j_unmap != NULL) + return (__db_jump.j_unmap(infop->addr, infop->size)); + +#ifdef HAVE_SHMGET + if (infop->segid != INVALID_SEGID) { + called = 1; + ret = shmdt(infop->addr) ? errno : 0; + } +#endif +#ifdef HAVE_MMAP + if (!called) { + called = 1; + ret = munmap(infop->addr, infop->size) ? errno : 0; + } +#endif + return (ret); +} + +/* + * __db_unlinkregion -- + * Remove the shared memory region. + * + * PUBLIC: int __db_unlinkregion __P((char *, REGINFO *)); + */ +int +__db_unlinkregion(name, infop) + char *name; + REGINFO *infop; +{ + int called, ret; + + called = 0; + ret = EINVAL; + + if (__db_jump.j_runlink != NULL) + return (__db_jump.j_runlink(name)); + +#ifdef HAVE_SHMGET + if (infop->segid != INVALID_SEGID) { + called = 1; + ret = shmctl(infop->segid, IPC_RMID, NULL) ? errno : 0; + } +#else + COMPQUIET(infop, NULL); +#endif +#ifdef HAVE_MMAP + if (!called) { + called = 1; + ret = 0; + } +#endif + return (ret); +} + +/* + * __db_mapfile -- + * Map in a shared memory file. + * + * PUBLIC: int __db_mapfile __P((char *, int, size_t, int, void **)); + */ +int +__db_mapfile(path, fd, len, is_rdonly, addr) + char *path; + int fd, is_rdonly; + size_t len; + void **addr; +{ + if (__db_jump.j_map != NULL) + return (__db_jump.j_map(path, fd, len, 0, 0, is_rdonly, addr)); + +#ifdef HAVE_MMAP + return (__os_map(path, fd, len, 0, 0, is_rdonly, addr)); +#else + return (EINVAL); +#endif +} + +/* + * __db_unmapfile -- + * Unmap the shared memory file. * - * PUBLIC: int __os_map __P((int, size_t, int, int, void **)); + * PUBLIC: int __db_unmapfile __P((void *, size_t)); */ int -__os_map(fd, len, is_private, is_rdonly, addr) - int fd, is_private, is_rdonly; +__db_unmapfile(addr, len) + void *addr; + size_t len; +{ + if (__db_jump.j_unmap != NULL) + return (__db_jump.j_unmap(addr, len)); + +#ifdef HAVE_MMAP + return (munmap(addr, len) ? errno : 0); +#else + return (EINVAL); +#endif +} + +#ifdef HAVE_MMAP +/* + * __os_map -- + * Call the mmap(2) function. + */ +static int +__os_map(path, fd, len, is_region, is_anonymous, is_rdonly, addr) + char *path; + int fd, is_region, is_anonymous, is_rdonly; size_t len; void **addr; { void *p; int flags, prot; - flags = is_private ? MAP_PRIVATE : MAP_SHARED; + COMPQUIET(path, NULL); + + /* + * If it's read-only, it's private, and if it's not, it's shared. + * Don't bother with an additional parameter. + */ + flags = is_rdonly ? MAP_PRIVATE : MAP_SHARED; + + if (is_region && is_anonymous) { + /* + * BSD derived systems use MAP_ANON; Digital Unix and HP/UX + * use MAP_ANONYMOUS. + */ +#ifdef MAP_ANON + flags |= MAP_ANON; +#endif +#ifdef MAP_ANONYMOUS + flags |= MAP_ANONYMOUS; +#endif + fd = -1; + } +#ifdef MAP_FILE + if (!is_region || !is_anonymous) { + /* + * Historically, MAP_FILE was required for mapping regular + * files, even though it was the default. Some systems have + * it, some don't, some that have it set it to 0. + */ + flags |= MAP_FILE; + } +#endif + + /* + * I know of no systems that implement the flag to tell the system + * that the region contains semaphores, but it's not an unreasonable + * thing to do, and has been part of the design since forever. I + * don't think anyone will object, but don't set it for read-only + * files, it doesn't make sense. + */ #ifdef MAP_HASSEMAPHORE - flags |= MAP_HASSEMAPHORE; + if (!is_rdonly) + flags |= MAP_HASSEMAPHORE; #endif + prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE); -#ifndef MAP_FAILED /* XXX: Mmap(2) failure return. */ + /* MAP_FAILED was not defined in early mmap implementations. */ +#ifndef MAP_FAILED #define MAP_FAILED -1 #endif if ((p = @@ -51,21 +399,67 @@ __os_map(fd, len, is_private, is_rdonly, addr) *addr = p; return (0); } +#endif +#ifdef HAVE_SHMGET /* - * __os_unmap -- - * Release the specified shared memory. - * - * PUBLIC: int __os_unmap __P((void *, size_t)); + * __os_shmget -- + * Call the shmget(2) family of functions. */ -int -__os_unmap(addr, len) - void *addr; - size_t len; +static int +__os_shmget(path, infop) + REGINFO *infop; + char *path; { - /* - * !!! - * The argument len is always the same length as was mapped. - */ - return (munmap(addr, len) ? errno : 0); + key_t key; + int shmflg; + + if (F_ISSET(infop, REGION_CREATED)) { + /* + * The return key from ftok(3) is not guaranteed to be unique. + * The nice thing about the shmget(2) interface is that it + * allows you to name anonymous pieces of memory. The evil + * thing about it is that the name space is separate from the + * filesystem. + */ +#ifdef __hp3000s900 + {char mpe_path[MAXPATHLEN]; + /* + * MPE ftok() is broken as of 5.5pp4. If the file path does + * not start with '/' or '.', then ftok() tries to interpret + * the file path in MPE syntax instead of POSIX HFS syntax. + * The workaround is to prepend "./" to these paths. See HP + * SR 5003416081 for details. + */ + if (*path != '/' && *path != '.') { + if (strlen(path) + strlen("./") + 1 > sizeof(mpe_path)) + return (ENAMETOOLONG); + mpe_path[0] = '.'; + mpe_path[1] = '/'; + (void)strcpy(mpe_path + 2, path); + path = mpe_path; + } + } +#endif + if ((key = ftok(path, 1)) == (key_t)-1) + return (errno); + + shmflg = IPC_CREAT | 0600; + if ((infop->segid = shmget(key, infop->size, shmflg)) == -1) + return (errno); + } + + if ((infop->addr = shmat(infop->segid, NULL, 0)) == (void *)-1) { + /* + * If we're trying to join the region and failing, assume + * that there was a reboot and the region no longer exists. + */ + if (!F_ISSET(infop, REGION_CREATED)) + errno = EAGAIN; + return (errno); + } + + F_SET(infop, REGION_HOLDINGSYS); + return (0); } +#endif |