diff --git a/src/common/isc_s_proto.h b/src/common/isc_s_proto.h index f5889159a20..72cb066de3a 100644 --- a/src/common/isc_s_proto.h +++ b/src/common/isc_s_proto.h @@ -279,6 +279,9 @@ class SharedMemoryBase int eventWait(event_t* event, const SLONG value, const SLONG micro_seconds); int eventPost(event_t* event); + // Used as memory allocation unit and mapping alignment + static ULONG getSystemPageSize(Firebird::CheckStatusWrapper* status); + public: #ifdef UNIX Firebird::AutoPtr mainLock; @@ -296,6 +299,7 @@ class SharedMemoryBase #endif ULONG sh_mem_length_mapped; + ULONG sh_mem_increment; // Suggested growth increment #ifdef WIN_NT HANDLE sh_mem_handle; // file handle HANDLE sh_mem_object; // file mapping diff --git a/src/common/isc_sync.cpp b/src/common/isc_sync.cpp index 58aad818fed..9998406e93f 100644 --- a/src/common/isc_sync.cpp +++ b/src/common/isc_sync.cpp @@ -1250,12 +1250,38 @@ void SharedMemoryBase::internalUnmap() } } + +ULONG SharedMemoryBase::getSystemPageSize(CheckStatusWrapper* statusVector) +{ + // Get system page size as this is the unit of mapping. + +#ifdef SOLARIS + const long ps = sysconf(_SC_PAGESIZE); + if (ps == -1) + { + error(statusVector, "sysconf", errno); + return 0; + } +#else + const int ps = getpagesize(); + if (ps == -1) + { + error(statusVector, "getpagesize", errno); + return 0; + } +#endif + return ps; +} + + SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject* callback, bool skipLock) : #ifdef HAVE_SHARED_MUTEX_SECTION sh_mem_mutex(0), #endif - sh_mem_length_mapped(0), sh_mem_header(NULL), + sh_mem_length_mapped(0), + sh_mem_increment(0), + sh_mem_header(NULL), sh_mem_callback(callback) { /************************************** @@ -1286,6 +1312,14 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject TEXT init_filename[MAXPATHLEN]; iscPrefixLock(init_filename, INIT_FILE, true); + if (length) + { + sh_mem_increment = length = FB_ALIGN(length, getSystemPageSize(&statusVector)); + + if (statusVector.hasData()) + status_exception::raise(&statusVector); + } + const bool trunc_flag = (length != 0); // open the init lock file @@ -1569,8 +1603,17 @@ void SharedMemoryBase::internalUnmap() unlinkFile(); } + +ULONG SharedMemoryBase::getSystemPageSize(CheckStatusWrapper* /*statusVector*/) +{ + SYSTEM_INFO sys_info; + GetSystemInfo(&sys_info); + return sys_info.dwAllocationGranularity; +} + + SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject* cb, bool /*skipLock*/) - : sh_mem_mutex(0), sh_mem_length_mapped(0), + : sh_mem_mutex(0), sh_mem_length_mapped(0), sh_mem_increment(0), sh_mem_handle(INVALID_HANDLE_VALUE), sh_mem_object(0), sh_mem_interest(0), sh_mem_hdr_object(0), sh_mem_hdr_address(0), sh_mem_header(NULL), sh_mem_callback(cb), sh_mem_unlink(false) { @@ -1598,6 +1641,17 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject bool init_flag = false; DWORD err = 0; + if (length) + { + LocalStatus ls; + CheckStatusWrapper statusVector(&ls); + + sh_mem_increment = length = FB_ALIGN(length, getSystemPageSize(&statusVector)); + + if (statusVector.hasData()) + status_exception::raise(&statusVector); + } + // retry to attach to mmapped file if the process initializing dies during initialization. retry: @@ -1925,24 +1979,9 @@ UCHAR* SharedMemoryBase::mapObject(CheckStatusWrapper* statusVector, ULONG objec * **************************************/ - // Get system page size as this is the unit of mapping. - -#ifdef SOLARIS - const long ps = sysconf(_SC_PAGESIZE); - if (ps == -1) - { - error(statusVector, "sysconf", errno); + const ULONG page_size = getSystemPageSize(statusVector); + if (!page_size) return NULL; - } -#else - const int ps = getpagesize(); - if (ps == -1) - { - error(statusVector, "getpagesize", errno); - return NULL; - } -#endif - const ULONG page_size = (ULONG) ps; // Compute the start and end page-aligned offsets which contain the object being mapped. @@ -1980,24 +2019,9 @@ void SharedMemoryBase::unmapObject(CheckStatusWrapper* statusVector, UCHAR** obj * Zero the object pointer after a successful unmap. * **************************************/ - // Get system page size as this is the unit of mapping. - -#ifdef SOLARIS - const long ps = sysconf(_SC_PAGESIZE); - if (ps == -1) - { - error(statusVector, "sysconf", errno); - return; - } -#else - const int ps = getpagesize(); - if (ps == -1) - { - error(statusVector, "getpagesize", errno); + const size_t page_size = getSystemPageSize(statusVector); + if (!page_size) return; - } -#endif - const size_t page_size = (ULONG) ps; // Compute the start and end page-aligned addresses which contain the mapped object. @@ -2035,9 +2059,7 @@ UCHAR* SharedMemoryBase::mapObject(CheckStatusWrapper* statusVector, * **************************************/ - SYSTEM_INFO sys_info; - GetSystemInfo(&sys_info); - const ULONG page_size = sys_info.dwAllocationGranularity; + const ULONG page_size = getSystemPageSize(statusVector); // Compute the start and end page-aligned offsets which // contain the object being mapped. @@ -2047,6 +2069,8 @@ UCHAR* SharedMemoryBase::mapObject(CheckStatusWrapper* statusVector, const ULONG length = end - start; const HANDLE handle = sh_mem_object; + fb_assert(end <= sh_mem_length_mapped); + UCHAR* address = (UCHAR*) MapViewOfFile(handle, FILE_MAP_WRITE, 0, start, length); if (address == NULL) @@ -2075,9 +2099,7 @@ void SharedMemoryBase::unmapObject(CheckStatusWrapper* statusVector, * Zero the object pointer after a successful unmap. * **************************************/ - SYSTEM_INFO sys_info; - GetSystemInfo(&sys_info); - const size_t page_size = sys_info.dwAllocationGranularity; + const size_t page_size = getSystemPageSize(statusVector); // Compute the start and end page-aligned offsets which // contain the object being mapped. @@ -2497,6 +2519,8 @@ bool SharedMemoryBase::remapFile(CheckStatusWrapper* statusVector, ULONG new_len if (flag) { + new_length = FB_ALIGN(new_length, getSystemPageSize(statusVector)); + FB_UNUSED(os_utils::ftruncate(mainLock->getFd(), new_length)); if (new_length > sh_mem_length_mapped) @@ -2553,6 +2577,8 @@ bool SharedMemoryBase::remapFile(CheckStatusWrapper* statusVector, if (flag) { + new_length = FB_ALIGN(new_length, getSystemPageSize(statusVector)); + LARGE_INTEGER offset; offset.QuadPart = new_length; diff --git a/src/jrd/event.cpp b/src/jrd/event.cpp index ffbb4e1bb59..59b8139f9ad 100644 --- a/src/jrd/event.cpp +++ b/src/jrd/event.cpp @@ -534,8 +534,10 @@ frb* EventManager::alloc_global(UCHAR type, ULONG length, bool recurse) #ifdef HAVE_OBJECT_MAP if (!best && !recurse) { + fb_assert(length <= m_sharedMemory->sh_mem_increment); + const ULONG old_length = m_sharedMemory->sh_mem_length_mapped; - const ULONG ev_length = old_length + m_config->getEventMemSize(); + const ULONG ev_length = old_length + m_sharedMemory->sh_mem_increment; LocalStatus ls; CheckStatusWrapper localStatus(&ls); diff --git a/src/lock/lock.cpp b/src/lock/lock.cpp index 3739f3ce6af..42cc614f17b 100644 --- a/src/lock/lock.cpp +++ b/src/lock/lock.cpp @@ -177,11 +177,26 @@ LockManager::LockManager(const string& id, const Config* conf) m_config(conf), m_acquireSpins(m_config->getLockAcquireSpins()), m_memorySize(m_config->getLockMemSize()), + m_hashSlots(m_config->getLockHashSlots()), m_useBlockingThread(m_config->getServerMode() != MODE_SUPER) #ifdef USE_SHMEM_EXT , m_extents(getPool()) #endif { + if (m_hashSlots < HASH_MIN_SLOTS) + m_hashSlots = HASH_MIN_SLOTS; + if (m_hashSlots > HASH_MAX_SLOTS) + m_hashSlots = HASH_MAX_SLOTS; + + // memory size required to fit all hash slots, history blocks and header blocks + const auto minMemory = sizeof(lhb) + + FB_ALIGN(sizeof(shb), FB_ALIGNMENT) + + sizeof(lhb::lhb_hash[0]) * m_hashSlots + + FB_ALIGN(sizeof(his), FB_ALIGNMENT) * HISTORY_BLOCKS * 2; + + if (m_memorySize < minMemory) + m_memorySize = minMemory; + LocalStatus ls; CheckStatusWrapper localStatus(&ls); if (!init_shared_file(&localStatus)) @@ -304,6 +319,9 @@ bool LockManager::init_shared_file(CheckStatusWrapper* statusVector) const auto header = tmp->getHeader(); checkHeader(header); + + // Get properly aligned value + m_memorySize = m_sharedMemory->sh_mem_increment; } catch (const Exception& ex) { @@ -2330,13 +2348,7 @@ bool LockManager::initialize(SharedMemoryBase* sm, bool initializeMemory) SRQ_INIT(hdr->lhb_free_locks); SRQ_INIT(hdr->lhb_free_requests); - int hash_slots = m_config->getLockHashSlots(); - if (hash_slots < HASH_MIN_SLOTS) - hash_slots = HASH_MIN_SLOTS; - if (hash_slots > HASH_MAX_SLOTS) - hash_slots = HASH_MAX_SLOTS; - - hdr->lhb_hash_slots = (USHORT) hash_slots; + hdr->lhb_hash_slots = m_hashSlots; hdr->lhb_scan_interval = m_config->getDeadlockTimeout(); hdr->lhb_acquire_spins = m_acquireSpins; diff --git a/src/lock/lock_proto.h b/src/lock/lock_proto.h index b0b14511938..444c6c51e8b 100644 --- a/src/lock/lock_proto.h +++ b/src/lock/lock_proto.h @@ -507,7 +507,8 @@ class LockManager final : public Firebird::GlobalStorage, public Firebird::IpcOb // configurations parameters - cached values const ULONG m_acquireSpins; - const ULONG m_memorySize; + ULONG m_memorySize; + USHORT m_hashSlots; const bool m_useBlockingThread; #ifdef USE_SHMEM_EXT