diff --git a/ircd/Makefile.am b/ircd/Makefile.am index 5b218e1a3..3616e437c 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -136,6 +136,7 @@ libircd_la_SOURCES += mods.cc if LINUX libircd_la_SOURCES += mods_ldso.cc endif +libircd_la_SOURCES += db_write_thread.cc libircd_la_SOURCES += db_port.cc libircd_la_SOURCES += db_env.cc libircd_la_SOURCES += db.cc @@ -156,6 +157,9 @@ libircd_la_SOURCES += m.cc libircd_la_SOURCES += m_event.cc libircd_la_SOURCES += ircd.cc +db_write_thread.lo: AM_CPPFLAGS += -I$(top_srcdir)/deps/rocksdb/include +db_write_thread.lo: AM_CPPFLAGS += -I$(top_srcdir)/deps/rocksdb + # Units containing a spirit grammar have some special needs to mitigate # larger-than-normal compile time, compile memory, and output objects. # A composite of CXXFLAGS is used specifically on units with grammars. diff --git a/ircd/db_write_thread.cc b/ircd/db_write_thread.cc new file mode 100644 index 000000000..cd8005e79 --- /dev/null +++ b/ircd/db_write_thread.cc @@ -0,0 +1,51 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#if __has_include("db/write_thread.h") + #define ROCKSDB_PLATFORM_POSIX + #include "db/write_thread.h" +#endif + +#ifndef STORAGE_ROCKSDB_INCLUDE_DB_H_ + #warning "The RocksDB source code is not available. Cannot interpose bugfixes for db/write_thread.h." +#endif + +#ifdef STORAGE_ROCKSDB_INCLUDE_DB_H_ +uint8_t +__attribute__((externally_visible)) +rocksdb::WriteThread::BlockingAwaitState(Writer *const w, + uint8_t goal_mask) +{ + // Create the class member mutex and cv where it's expected by + // rocksdb callers + w->CreateMutex(); + + auto state(w->state.load(std::memory_order_acquire)); + assert(state != STATE_LOCKED_WAITING); + if((state & goal_mask) == 0 && w->state.compare_exchange_strong(state, STATE_LOCKED_WAITING)) + { + size_t yields(0); + while((state = w->state.load(std::memory_order_relaxed)) == STATE_LOCKED_WAITING) + { + ircd::ctx::yield(); + ++yields; + } + + // Since we're using a coarse ctx::yield() it's theoretically possible + // that our loop can spin out of control. That is highly unlikely, + // and there is usually not even more than one iteration. Nevertheless + // we assert to be sure this is working within reason. + assert(yields < 32); + } + + assert((state & goal_mask) != 0); + return state; +} +#endif STORAGE_ROCKSDB_INCLUDE_DB_H_