Commit f9861598 authored by Xavier Thompson's avatar Xavier Thompson

Add source context to cypclass data race logging

parent ebe5882e
...@@ -14010,10 +14010,22 @@ class CoerceToLockedTempNode(CoerceToTempNode): ...@@ -14010,10 +14010,22 @@ class CoerceToLockedTempNode(CoerceToTempNode):
def generate_result_code(self, code): def generate_result_code(self, code):
super(CoerceToLockedTempNode, self).generate_result_code(code) super(CoerceToLockedTempNode, self).generate_result_code(code)
#XXX Code duplicated from Nodes.LockCypclassNode
if self.arg.pos:
source_descr, lineno, colno = self.arg.pos
source_str = source_descr.get_description()
source_lines = source_descr.get_lines()
line_str = source_lines[lineno - 1]
col_str = "%s%s" % (' ' * colno, '^')
context = "%s:%d:%d\n%s%s" % (source_str, lineno, colno, line_str, col_str)
context = code.get_string_const(StringEncoding.EncodedString(context))
else:
context = "NULL"
if self.rlock_only: if self.rlock_only:
code.putln("Cy_RLOCK(%s);" % self.result()) code.putln("Cy_RLOCK_CONTEXT(%s, %s);" % (self.result(), context))
else: else:
code.putln("Cy_WLOCK(%s);" % self.result()) code.putln("Cy_WLOCK_CONTEXT(%s, %s);" % (self.result(), context))
def generate_disposal_code(self, code): def generate_disposal_code(self, code):
if self.rlock_only: if self.rlock_only:
......
...@@ -8558,10 +8558,17 @@ class LockCypclassNode(StatNode): ...@@ -8558,10 +8558,17 @@ class LockCypclassNode(StatNode):
def generate_execution_code(self, code): def generate_execution_code(self, code):
self.obj.generate_evaluation_code(code) self.obj.generate_evaluation_code(code)
# As we're relying on a recursive and upgradable lock, if self.obj.pos:
# we don't need to care about things like unlocking a read lock source_descr, lineno, colno = self.obj.pos
# before taking a write lock, so the code is quite brutal here. source_str = source_descr.get_description()
lock_code = "Cy_%s(%s);" % (self.state[:-2].upper(), self.obj.result()) source_lines = source_descr.get_lines()
line_str = source_lines[lineno - 1]
col_str = "%s%s" % (' ' * colno, '^')
context = "%s:%d:%d\n%s%s" % (source_str, lineno, colno, line_str, col_str)
context = code.get_string_const(EncodedString(context))
else:
context = "NULL"
lock_code = "Cy_%s_CONTEXT(%s, %s);" % (self.state[:-2].upper(), self.obj.result(), context)
code.putln(lock_code) code.putln(lock_code)
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#define CyObject_CONTENDING_WRITER_FLAG (1 << 0) #define CyObject_CONTENDING_WRITER_FLAG (1 << 0)
#define CyObject_CONTENDING_READER_FLAG (1 << 1) #define CyObject_CONTENDING_READER_FLAG (1 << 1)
#define CyObject_RAISE_ON_CONTENTION 1 #define CyObject_RAISE_ON_CONTENTION 0
#include <pthread.h> #include <pthread.h>
...@@ -54,8 +54,8 @@ ...@@ -54,8 +54,8 @@
this->readers_nb = 0; this->readers_nb = 0;
this->write_count = 0; this->write_count = 0;
} }
void wlock(); void wlock(const char * context);
void rlock(); void rlock(const char * context);
void unwlock(); void unwlock();
void unrlock(); void unrlock();
int tryrlock(); int tryrlock();
...@@ -79,8 +79,8 @@ ...@@ -79,8 +79,8 @@
void CyObject_INCREF(); void CyObject_INCREF();
int CyObject_DECREF(); int CyObject_DECREF();
int CyObject_GETREF(); int CyObject_GETREF();
void CyObject_RLOCK(); void CyObject_RLOCK(const char * context);
void CyObject_WLOCK(); void CyObject_WLOCK(const char * context);
void CyObject_UNRLOCK(); void CyObject_UNRLOCK();
void CyObject_UNWLOCK(); void CyObject_UNWLOCK();
int CyObject_TRYRLOCK(); int CyObject_TRYRLOCK();
...@@ -167,18 +167,18 @@ ...@@ -167,18 +167,18 @@
return ob->CyObject_GETREF(); return ob->CyObject_GETREF();
} }
static inline void _Cy_RLOCK(CyObject *ob) { static inline void _Cy_RLOCK(CyObject *ob, const char *context) {
if (ob != NULL) { if (ob != NULL) {
ob->CyObject_RLOCK(); ob->CyObject_RLOCK(context);
} }
else { else {
fprintf(stderr, "ERROR: trying to read lock NULL !\n"); fprintf(stderr, "ERROR: trying to read lock NULL !\n");
} }
} }
static inline void _Cy_WLOCK(CyObject *ob) { static inline void _Cy_WLOCK(CyObject *ob, const char *context) {
if (ob != NULL) { if (ob != NULL) {
ob->CyObject_WLOCK(); ob->CyObject_WLOCK(context);
} }
else { else {
fprintf(stderr, "ERROR: trying to write lock NULL !\n"); fprintf(stderr, "ERROR: trying to write lock NULL !\n");
...@@ -291,8 +291,10 @@ ...@@ -291,8 +291,10 @@
#define Cy_XGOTREF(ob) #define Cy_XGOTREF(ob)
#define Cy_GIVEREF(ob) #define Cy_GIVEREF(ob)
#define Cy_XGIVEREF(ob) #define Cy_XGIVEREF(ob)
#define Cy_RLOCK(ob) _Cy_RLOCK(ob) #define Cy_RLOCK(ob) _Cy_RLOCK(ob, NULL)
#define Cy_WLOCK(ob) _Cy_WLOCK(ob) #define Cy_WLOCK(ob) _Cy_WLOCK(ob, NULL)
#define Cy_RLOCK_CONTEXT(ob, context) _Cy_RLOCK(ob, context)
#define Cy_WLOCK_CONTEXT(ob, context) _Cy_WLOCK(ob, context)
#define Cy_UNRLOCK(ob) _Cy_UNRLOCK(ob) #define Cy_UNRLOCK(ob) _Cy_UNRLOCK(ob)
#define Cy_UNWLOCK(ob) _Cy_UNWLOCK(ob) #define Cy_UNWLOCK(ob) _Cy_UNWLOCK(ob)
#define Cy_TRYRLOCK(ob) _Cy_TRYRLOCK(ob) #define Cy_TRYRLOCK(ob) _Cy_TRYRLOCK(ob)
...@@ -307,6 +309,7 @@ ...@@ -307,6 +309,7 @@
#include <cstdlib> #include <cstdlib>
#include <cstddef> #include <cstddef>
#include <sstream> #include <sstream>
#include <iostream>
#include <stdexcept> #include <stdexcept>
// atomic is already included in ModuleSetupCode // atomic is already included in ModuleSetupCode
// #include <atomic> // #include <atomic>
...@@ -315,7 +318,7 @@ ...@@ -315,7 +318,7 @@
#endif /* __cplusplus */ #endif /* __cplusplus */
void CyLock::rlock() { void CyLock::rlock(const char *context) {
pid_t caller_id = syscall(SYS_gettid); pid_t caller_id = syscall(SYS_gettid);
if (this->owner_id == caller_id) { if (this->owner_id == caller_id) {
...@@ -329,17 +332,23 @@ void CyLock::rlock() { ...@@ -329,17 +332,23 @@ void CyLock::rlock() {
#if CyObject_RAISE_ON_CONTENTION #if CyObject_RAISE_ON_CONTENTION
pid_t owner_id = this->owner_id; pid_t owner_id = this->owner_id;
std::ostringstream msg; std::ostringstream msg;
msg << "Data Race between [this] reader #" << caller_id << " and [other] writer #" << owner_id << " on lock " << this; msg << "Data Race between [this] reader #" << caller_id
<< " and [other] writer #" << owner_id
<< " on lock " << this;
if (context != NULL) {
msg << std::endl << "In: " << context;
}
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
#else #else
pid_t owner_id = this->owner_id; pid_t owner_id = this->owner_id;
pthread_mutex_lock(&(CyLock::log_guard)); pthread_mutex_lock(&(CyLock::log_guard));
printf( std::cout
"Contention with a writer detected while rlocking lock [%p] in thread #%d:\n" << "Data Race between [this] reader #" << caller_id
" - lock was already wlocked by thread %d\n" << " and [other] writer #" << owner_id
"\n" << " on lock " << this << std::endl;
,this, caller_id, owner_id if (context != NULL) {
); std::cout << "In: " << context << std::endl;
}
pthread_mutex_unlock(&(CyLock::log_guard)); pthread_mutex_unlock(&(CyLock::log_guard));
#endif #endif
} }
...@@ -392,7 +401,7 @@ void CyLock::unrlock() { ...@@ -392,7 +401,7 @@ void CyLock::unrlock() {
pthread_mutex_unlock(&this->guard); pthread_mutex_unlock(&this->guard);
} }
void CyLock::wlock() { void CyLock::wlock(const char *context) {
pid_t caller_id = syscall(SYS_gettid); pid_t caller_id = syscall(SYS_gettid);
if (this->owner_id == caller_id) { if (this->owner_id == caller_id) {
...@@ -415,27 +424,20 @@ void CyLock::wlock() { ...@@ -415,27 +424,20 @@ void CyLock::wlock() {
#if CyObject_RAISE_ON_CONTENTION #if CyObject_RAISE_ON_CONTENTION
pid_t owner_id = this->owner_id; pid_t owner_id = this->owner_id;
std::ostringstream msg; std::ostringstream msg;
msg << "Data Race between [this] writer #" << caller_id << " and [other] reader #" << owner_id << " on lock " << this; msg << "Data Race between [this] writer #" << caller_id
<< " and [other] reader #" << owner_id
<< " on lock " << this;
if (context != NULL) {
msg << std::endl << "In: " << context;
}
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
#else #else
if (owner_id == CyObject_MANY_OWNERS) { std::cout
pthread_mutex_lock(&(CyLock::log_guard)); << "Data Race between [this] writer #" << caller_id
printf( << " and [other] reader #" << owner_id
"Contention with several other reader threads detected while wlocking lock [%p] in thread #%d:\n" << " on lock " << this << std::endl;
"\n" if (context != NULL) {
,this, caller_id std::cout << "In: " << context << std::endl;
);
pthread_mutex_unlock(&(CyLock::log_guard));
}
else {
pthread_mutex_lock(&(CyLock::log_guard));
printf(
"Contention with a reader thread detected while wlocking lock [%p] in thread #%d:\n"
" - reader thread is %d\n"
"\n"
,this, caller_id, owner_id
);
pthread_mutex_unlock(&(CyLock::log_guard));
} }
#endif #endif
} }
...@@ -448,16 +450,22 @@ void CyLock::wlock() { ...@@ -448,16 +450,22 @@ void CyLock::wlock() {
#if CyObject_RAISE_ON_CONTENTION #if CyObject_RAISE_ON_CONTENTION
pid_t owner_id = this->owner_id; pid_t owner_id = this->owner_id;
std::ostringstream msg; std::ostringstream msg;
msg << "Data Race between [this] writer #" << caller_id << " and [other] writer #" << owner_id << " on lock " << this; msg << "Data Race between [this] writer #" << caller_id
<< " and [other] writer #" << owner_id
<< " on lock " << this;
if (context != NULL) {
msg << std::endl << "In: " << context;
}
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
#else #else
pthread_mutex_lock(&(CyLock::log_guard)); pthread_mutex_lock(&(CyLock::log_guard));
printf( std::cout
"Contention with another writer detected while wlocking lock [%p] in thread #%d:\n" << "Data Race between [this] writer #" << caller_id
" - lock was already wlocked by thread %d\n" << " and [other] writer #" << owner_id
"\n" << " on lock " << this << std::endl;
,this, caller_id, owner_id if (context != NULL) {
); std::cout << "In: " << context << std::endl;
}
pthread_mutex_unlock(&(CyLock::log_guard)); pthread_mutex_unlock(&(CyLock::log_guard));
#endif #endif
} }
...@@ -547,14 +555,14 @@ int CyObject::CyObject_GETREF() ...@@ -547,14 +555,14 @@ int CyObject::CyObject_GETREF()
return this->nogil_ob_refcnt; return this->nogil_ob_refcnt;
} }
void CyObject::CyObject_RLOCK() void CyObject::CyObject_RLOCK(const char *context)
{ {
this->ob_lock.rlock(); this->ob_lock.rlock(context);
} }
void CyObject::CyObject_WLOCK() void CyObject::CyObject_WLOCK(const char *context)
{ {
this->ob_lock.wlock(); this->ob_lock.wlock(context);
} }
int CyObject::CyObject_TRYRLOCK() int CyObject::CyObject_TRYRLOCK()
......
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