Commit fe5fc746 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Purge the old GRWL (gil-free) code

It's time :(
parent d7be5092
......@@ -37,8 +37,6 @@
namespace pyston {
DS_DEFINE_RWLOCK(codegen_rwlock);
FunctionMetadata::FunctionMetadata(int num_args, bool takes_varargs, bool takes_kwargs,
std::unique_ptr<SourceInfo> source)
: code_obj(NULL),
......
......@@ -90,8 +90,6 @@ extern GlobalState g;
// in runtime_hooks.cpp:
void initGlobalFuncs(GlobalState& g);
DS_DECLARE_RWLOCK(codegen_rwlock);
}
#endif
......@@ -341,30 +341,26 @@ CompiledFunction* compileFunction(FunctionMetadata* f, FunctionSpecialization* s
void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
FunctionMetadata* md;
{ // scope for limiting the locked region:
LOCK_REGION(codegen_rwlock.asWrite());
Timer _t("for compileModule()");
Timer _t("for compileModule()");
const char* fn = PyModule_GetFilename(bm);
RELEASE_ASSERT(fn, "");
const char* fn = PyModule_GetFilename(bm);
RELEASE_ASSERT(fn, "");
FutureFlags future_flags = getFutureFlags(m->body, fn);
ScopingAnalysis* scoping = new ScopingAnalysis(m, true);
FutureFlags future_flags = getFutureFlags(m->body, fn);
ScopingAnalysis* scoping = new ScopingAnalysis(m, true);
auto fn_str = boxString(fn);
AUTO_DECREF(fn_str);
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, fn_str));
auto fn_str = boxString(fn);
AUTO_DECREF(fn_str);
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, fn_str));
static BoxedString* doc_str = getStaticString("__doc__");
bm->setattr(doc_str, autoDecref(si->getDocString()), NULL);
static BoxedString* doc_str = getStaticString("__doc__");
bm->setattr(doc_str, autoDecref(si->getDocString()), NULL);
static BoxedString* builtins_str = getStaticString("__builtins__");
if (!bm->hasattr(builtins_str))
bm->setattr(builtins_str, PyModule_GetDict(builtins_module), NULL);
static BoxedString* builtins_str = getStaticString("__builtins__");
if (!bm->hasattr(builtins_str))
bm->setattr(builtins_str, PyModule_GetDict(builtins_module), NULL);
md = new FunctionMetadata(0, false, false, std::move(si));
}
md = new FunctionMetadata(0, false, false, std::move(si));
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_interpreted_module_toplevel");
Box* r = astInterpretFunction(md, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
......@@ -395,8 +391,6 @@ Box* evalOrExec(FunctionMetadata* md, Box* globals, Box* boxedLocals) {
static FunctionMetadata* compileForEvalOrExec(AST* source, llvm::ArrayRef<AST_stmt*> body, BoxedString* fn,
PyCompilerFlags* flags) {
LOCK_REGION(codegen_rwlock.asWrite());
Timer _t("for evalOrExec()");
ScopingAnalysis* scoping = new ScopingAnalysis(source, false);
......@@ -655,8 +649,6 @@ void exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_f
// TODO we should have logic like this at the CLFunc level that detects that we keep
// on creating functions with failing speculations, and then stop speculating.
void CompiledFunction::speculationFailed() {
LOCK_REGION(codegen_rwlock.asWrite());
this->times_speculation_failed++;
if (this->times_speculation_failed == 4) {
......@@ -735,8 +727,6 @@ ConcreteCompilerType* CompiledFunction::getReturnType() {
/// The cf must be an active version in its parents FunctionMetadata; the given
/// version will be replaced by the new version, which will be returned.
static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel new_effort) {
LOCK_REGION(codegen_rwlock.asWrite());
assert(cf->md->versions.size());
assert(cf);
......@@ -773,8 +763,6 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel new_effort)
static StatCounter stat_osrexits("num_osr_exits");
static StatCounter stat_osr_compiles("num_osr_compiles");
CompiledFunction* compilePartialFuncInternal(OSRExit* exit) {
LOCK_REGION(codegen_rwlock.asWrite());
assert(exit);
stat_osrexits.log();
......
......@@ -36,6 +36,8 @@
namespace pyston {
namespace threading {
void _acquireGIL();
void _releaseGIL();
#ifdef WITH_THREAD
#include "pythread.h"
......@@ -99,14 +101,14 @@ public:
return holds_gil;
}
void takeGil() {
void gilTaken() {
assert(pthread_self() == this->pthread_id);
assert(!holds_gil);
holds_gil = true;
}
void releaseGil() {
void gilReleased() {
assert(pthread_self() == this->pthread_id);
assert(holds_gil);
......@@ -197,7 +199,7 @@ extern "C" PyGILState_STATE PyGILState_Ensure(void) noexcept {
if (current_internal_thread_state == NULL)
Py_FatalError("Couldn't create thread-state for new thread");
acquireGLRead();
_acquireGIL();
return PyGILState_UNLOCKED;
} else {
++cur_thread_state.gilstate_counter;
......@@ -246,13 +248,14 @@ static void* _thread_start(void* _arg) {
Box* arg3 = arg->arg3;
delete arg;
threading::GLReadRegion _glock;
_acquireGIL();
registerThread(true);
assert(!PyErr_Occurred());
void* rtn = start_func(arg1, arg2, arg3);
unregisterThread();
_releaseGIL();
return rtn;
}
......@@ -296,6 +299,8 @@ void registerMainThread() {
assert(!current_internal_thread_state);
current_internal_thread_state = new ThreadStateInternal(pthread_self(), &cur_thread_state);
current_threads[pthread_self()] = current_internal_thread_state;
_acquireGIL();
}
/* Wait until threading._shutdown completes, provided
......@@ -344,28 +349,23 @@ extern "C" void beginAllowThreads() noexcept {
LOCK_REGION(&threading_lock);
assert(current_internal_thread_state);
current_internal_thread_state->releaseGil();
current_internal_thread_state->gilReleased();
}
releaseGLRead();
_releaseGIL();
}
extern "C" void endAllowThreads() noexcept {
acquireGLRead();
_acquireGIL();
{
LOCK_REGION(&threading_lock);
assert(current_internal_thread_state);
current_internal_thread_state->takeGil();
current_internal_thread_state->gilTaken();
}
}
#if THREADING_USE_GIL
#if THREADING_USE_GRWL
#error "Can't turn on both the GIL and the GRWL!"
#endif
static pthread_mutex_t gil = PTHREAD_MUTEX_INITIALIZER;
std::atomic<int> threads_waiting_on_gil(0);
......@@ -423,7 +423,7 @@ extern "C" void PyEval_ReInitThreads() noexcept {
Py_DECREF(threading);
}
void acquireGLWrite() {
void _acquireGIL() {
threads_waiting_on_gil++;
pthread_mutex_lock(&gil);
threads_waiting_on_gil--;
......@@ -431,7 +431,7 @@ void acquireGLWrite() {
pthread_cond_signal(&gil_acquired);
}
void releaseGLWrite() {
void _releaseGIL() {
pthread_mutex_unlock(&gil);
}
......@@ -457,86 +457,6 @@ void _allowGLReadPreemption() {
threads_waiting_on_gil--;
pthread_cond_signal(&gil_acquired);
}
#elif THREADING_USE_GRWL
static pthread_rwlock_t grwl = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
enum class GRWLHeldState {
N,
R,
W,
};
static __thread GRWLHeldState grwl_state = GRWLHeldState::N;
static std::atomic<int> writers_waiting(0);
void acquireGLRead() {
assert(grwl_state == GRWLHeldState::N);
pthread_rwlock_rdlock(&grwl);
grwl_state = GRWLHeldState::R;
}
void releaseGLRead() {
assert(grwl_state == GRWLHeldState::R);
pthread_rwlock_unlock(&grwl);
grwl_state = GRWLHeldState::N;
}
void acquireGLWrite() {
assert(grwl_state == GRWLHeldState::N);
writers_waiting++;
pthread_rwlock_wrlock(&grwl);
writers_waiting--;
grwl_state = GRWLHeldState::W;
}
void releaseGLWrite() {
assert(grwl_state == GRWLHeldState::W);
pthread_rwlock_unlock(&grwl);
grwl_state = GRWLHeldState::N;
}
void promoteGL() {
Timer _t2("promoting", /*min_usec=*/10000);
// Note: this is *not* the same semantics as normal promoting, on purpose.
releaseGLRead();
acquireGLWrite();
long promote_us = _t2.end();
static thread_local StatPerThreadCounter sc_promoting_us("grwl_promoting_us");
sc_promoting_us.log(promote_us);
}
void demoteGL() {
releaseGLWrite();
acquireGLRead();
}
static __thread int gl_check_count = 0;
void allowGLReadPreemption() {
assert(grwl_state == GRWLHeldState::R);
// gl_check_count++;
// if (gl_check_count < 10)
// return;
// gl_check_count = 0;
if (__builtin_expect(!writers_waiting.load(std::memory_order_relaxed), 1))
return;
Timer _t2("preempted", /*min_usec=*/10000);
pthread_rwlock_unlock(&grwl);
// The GRWL is a writer-prefered rwlock, so this next statement will block even
// if the lock is in read mode:
pthread_rwlock_rdlock(&grwl);
long preempt_us = _t2.end();
static thread_local StatPerThreadCounter sc_preempting_us("grwl_preempt_us");
sc_preempting_us.log(preempt_us);
}
#endif
// We don't support CPython's TLS (yet?)
extern "C" void PyThread_ReInitTLS(void) noexcept {
......
......@@ -47,35 +47,10 @@ void finishMainThread();
bool isMainThread();
#ifndef THREADING_USE_GIL
#define THREADING_USE_GIL 1
#define THREADING_USE_GRWL 0
#endif
#define THREADING_SAFE_DATASTRUCTURES THREADING_USE_GRWL
#if THREADING_SAFE_DATASTRUCTURES
#define DS_DEFINE_MUTEX(name) pyston::threading::PthreadFastMutex name
#define DS_DECLARE_RWLOCK(name) extern pyston::threading::PthreadRWLock name
#define DS_DEFINE_RWLOCK(name) pyston::threading::PthreadRWLock name
#define DS_DEFINE_SPINLOCK(name) pyston::threading::PthreadSpinLock name
#else
#define DS_DEFINE_MUTEX(name) pyston::threading::NopLock name
#define DS_DECLARE_RWLOCK(name) extern pyston::threading::NopLock name
#define DS_DEFINE_RWLOCK(name) pyston::threading::NopLock name
#define DS_DEFINE_SPINLOCK(name) pyston::threading::NopLock name
#endif
void acquireGLRead();
void releaseGLRead();
void acquireGLWrite();
void releaseGLWrite();
void _allowGLReadPreemption();
#define GIL_CHECK_INTERVAL 1000
// Note: this doesn't need to be an atomic, since it should
// only be accessed by the thread that holds the gil:
extern int gil_check_count;
......@@ -104,25 +79,7 @@ extern "C" inline void allowGLReadPreemption() {
_allowGLReadPreemption();
}
// Note: promoteGL is free to drop the lock and then reacquire
void promoteGL();
void demoteGL();
// Helper macro for creating a RAII wrapper around two functions.
#define MAKE_REGION(name, start, end) \
class name { \
public: \
name() { start(); } \
~name() { end(); } \
};
MAKE_REGION(GLReadRegion, acquireGLRead, releaseGLRead);
MAKE_REGION(GLPromoteRegion, promoteGL, demoteGL);
// MAKE_REGION(GLReadReleaseRegion, releaseGLRead, acquireGLRead);
// MAKE_REGION(GLWriteReleaseRegion, releaseGLWrite, acquireGLWrite);
#undef MAKE_REGION
extern "C" void beginAllowThreads() noexcept;
extern "C" void endAllowThreads() noexcept;
......@@ -134,37 +91,6 @@ public:
};
#if THREADING_USE_GIL
inline void acquireGLRead() {
acquireGLWrite();
}
inline void releaseGLRead() {
releaseGLWrite();
}
inline void promoteGL() {
}
inline void demoteGL() {
}
#endif
#if !THREADING_USE_GIL && !THREADING_USE_GRWL
inline void acquireGLRead() {
}
inline void releaseGLRead() {
}
inline void acquireGLWrite() {
}
inline void releaseGLWrite() {
}
inline void promoteGL() {
}
inline void demoteGL() {
}
extern "C" inline void allowGLReadPreemption() __attribute__((visibility("default")));
extern "C" inline void allowGLReadPreemption() {
}
#endif
extern bool forgot_refs_via_fork;
} // namespace threading
......
......@@ -369,7 +369,6 @@ static int main(int argc, char** argv) noexcept {
const char* fn = NULL;
threading::registerMainThread();
threading::acquireGLRead();
Py_SetProgramName(argv[0]);
......@@ -540,11 +539,6 @@ static int main(int argc, char** argv) noexcept {
threading::finishMainThread();
// Acquire the GIL to make sure we stop the other threads, since we will tear down
// data structures they are potentially running on.
// Note: we will purposefully not release the GIL on exiting.
threading::promoteGL();
_t.split("Py_Finalize");
Py_Finalize();
......
......@@ -3967,8 +3967,6 @@ static StatCounter slowpath_pickversion("slowpath_pickversion");
template <ExceptionStyle S>
static CompiledFunction* pickVersion(FunctionMetadata* f, int num_output_args, Box* oarg1, Box* oarg2, Box* oarg3,
Box** oargs) {
LOCK_REGION(codegen_rwlock.asWrite());
// if always_use_version is set use it even if the exception style does not match.
// But prefer using the correct style if both are available
if (f->always_use_version.get(S))
......
......@@ -25,12 +25,10 @@ namespace pyston {
class PystonTestEnvironment : public testing::Environment {
void SetUp() override {
threading::registerMainThread();
threading::acquireGLRead();
}
void TearDown() override {
threading::releaseGLRead();
// threading::releaseGLRead();
}
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment