Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xavier Thompson
cython
Commits
d4a204b6
Commit
d4a204b6
authored
Aug 14, 2020
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up cypclass object lock implementation
parent
b8672147
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
68 additions
and
136 deletions
+68
-136
Cython/Utility/CyObjects.cpp
Cython/Utility/CyObjects.cpp
+68
-136
No files found.
Cython/Utility/CyObjects.cpp
View file @
d4a204b6
...
@@ -34,19 +34,20 @@
...
@@ -34,19 +34,20 @@
#include <type_traits>
#include <type_traits>
class
RecursiveUpgradeableRWLock
{
class
CyLock
{
static
pthread_mutex_t
log_guard
;
protected:
protected:
pthread_mutex_t
guard
;
pthread_mutex_t
guard
;
pthread_cond_t
wait_readers_depar
t
;
pthread_cond_t
readers_have_lef
t
;
pthread_cond_t
w
ait_writer_depar
t
;
pthread_cond_t
w
riter_has_lef
t
;
atomic
<
pid_t
>
owner_id
;
atomic
<
pid_t
>
owner_id
;
atomic_int32_t
readers_nb
;
atomic_int32_t
readers_nb
;
uint32_t
write_count
;
uint32_t
write_count
;
public:
public:
RecursiveUpgradeableRW
Lock
()
{
Cy
Lock
()
{
pthread_mutex_init
(
&
this
->
guard
,
NULL
);
pthread_mutex_init
(
&
this
->
guard
,
NULL
);
pthread_cond_init
(
&
this
->
wait_readers_depar
t
,
NULL
);
pthread_cond_init
(
&
this
->
readers_have_lef
t
,
NULL
);
pthread_cond_init
(
&
this
->
w
ait_writer_depar
t
,
NULL
);
pthread_cond_init
(
&
this
->
w
riter_has_lef
t
,
NULL
);
this
->
owner_id
=
CyObject_NO_OWNER
;
this
->
owner_id
=
CyObject_NO_OWNER
;
this
->
readers_nb
=
0
;
this
->
readers_nb
=
0
;
this
->
write_count
=
0
;
this
->
write_count
=
0
;
...
@@ -58,14 +59,7 @@
...
@@ -58,14 +59,7 @@
int
tryrlock
();
int
tryrlock
();
int
trywlock
();
int
trywlock
();
};
};
pthread_mutex_t
CyLock
::
log_guard
=
PTHREAD_MUTEX_INITIALIZER
;
class
LogLock
:
public
RecursiveUpgradeableRWLock
{
static
pthread_mutex_t
log_guard
;
public:
void
wlock
();
void
rlock
();
};
pthread_mutex_t
LogLock
::
log_guard
=
PTHREAD_MUTEX_INITIALIZER
;
struct
CyPyObject
{
struct
CyPyObject
{
PyObject_HEAD
PyObject_HEAD
...
@@ -74,7 +68,7 @@
...
@@ -74,7 +68,7 @@
class
CyObject
:
public
CyPyObject
{
class
CyObject
:
public
CyPyObject
{
private:
private:
CyObject_ATOMIC_REFCOUNT_TYPE
nogil_ob_refcnt
;
CyObject_ATOMIC_REFCOUNT_TYPE
nogil_ob_refcnt
;
Log
Lock
ob_lock
;
Cy
Lock
ob_lock
;
public:
public:
CyObject
()
:
nogil_ob_refcnt
(
1
)
{}
CyObject
()
:
nogil_ob_refcnt
(
1
)
{}
virtual
~
CyObject
()
{}
virtual
~
CyObject
()
{}
...
@@ -315,7 +309,7 @@
...
@@ -315,7 +309,7 @@
#endif
/* __cplusplus */
#endif
/* __cplusplus */
void
RecursiveUpgradeableRW
Lock
::
rlock
()
{
void
Cy
Lock
::
rlock
()
{
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
)
{
...
@@ -325,8 +319,20 @@ void RecursiveUpgradeableRWLock::rlock() {
...
@@ -325,8 +319,20 @@ void RecursiveUpgradeableRWLock::rlock() {
pthread_mutex_lock
(
&
this
->
guard
);
pthread_mutex_lock
(
&
this
->
guard
);
if
(
this
->
write_count
>
0
)
{
pid_t
owner_id
=
this
->
owner_id
;
pthread_mutex_lock
(
&
(
CyLock
::
log_guard
));
printf
(
"Contention with a writer detected while rlocking lock [%p] in thread #%d:
\n
"
" - lock was already wlocked by thread %d
\n
"
"
\n
"
,
this
,
caller_id
,
owner_id
);
pthread_mutex_unlock
(
&
(
CyLock
::
log_guard
));
}
while
(
this
->
write_count
>
0
)
{
while
(
this
->
write_count
>
0
)
{
pthread_cond_wait
(
&
this
->
w
ait_writer_depar
t
,
&
this
->
guard
);
pthread_cond_wait
(
&
this
->
w
riter_has_lef
t
,
&
this
->
guard
);
}
}
this
->
owner_id
=
this
->
readers_nb
++
?
CyObject_MANY_OWNERS
:
caller_id
;
this
->
owner_id
=
this
->
readers_nb
++
?
CyObject_MANY_OWNERS
:
caller_id
;
...
@@ -334,7 +340,7 @@ void RecursiveUpgradeableRWLock::rlock() {
...
@@ -334,7 +340,7 @@ void RecursiveUpgradeableRWLock::rlock() {
pthread_mutex_unlock
(
&
this
->
guard
);
pthread_mutex_unlock
(
&
this
->
guard
);
}
}
int
RecursiveUpgradeableRW
Lock
::
tryrlock
()
{
int
Cy
Lock
::
tryrlock
()
{
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
)
{
...
@@ -358,8 +364,7 @@ int RecursiveUpgradeableRWLock::tryrlock() {
...
@@ -358,8 +364,7 @@ int RecursiveUpgradeableRWLock::tryrlock() {
return
0
;
return
0
;
}
}
void
RecursiveUpgradeableRWLock
::
unrlock
()
{
void
CyLock
::
unrlock
()
{
pthread_mutex_lock
(
&
this
->
guard
);
pthread_mutex_lock
(
&
this
->
guard
);
if
(
--
this
->
readers_nb
==
0
)
{
if
(
--
this
->
readers_nb
==
0
)
{
...
@@ -368,13 +373,13 @@ void RecursiveUpgradeableRWLock::unrlock() {
...
@@ -368,13 +373,13 @@ void RecursiveUpgradeableRWLock::unrlock() {
}
}
// broadcast to wake up all the waiting writers
// broadcast to wake up all the waiting writers
pthread_cond_broadcast
(
&
this
->
wait_readers_depar
t
);
pthread_cond_broadcast
(
&
this
->
readers_have_lef
t
);
}
}
pthread_mutex_unlock
(
&
this
->
guard
);
pthread_mutex_unlock
(
&
this
->
guard
);
}
}
void
RecursiveUpgradeableRW
Lock
::
wlock
()
{
void
Cy
Lock
::
wlock
()
{
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
)
{
...
@@ -386,26 +391,52 @@ void RecursiveUpgradeableRWLock::wlock() {
...
@@ -386,26 +391,52 @@ void RecursiveUpgradeableRWLock::wlock() {
pthread_mutex_lock
(
&
this
->
guard
);
pthread_mutex_lock
(
&
this
->
guard
);
if
(
this
->
owner_id
!=
caller_id
)
{
pid_t
owner_id
=
this
->
owner_id
;
// we wait for readers first and bottleneck the writers after
// this works for a readers preferring approach
// because the other way around would require setting write_count to 1 before waiting on the readers
if
(
owner_id
!=
caller_id
)
{
// in order to ensure only one writer at a times goes beyound waiting for the other writers to leave
//
this would be more in line with a writers preferring approach, but that can deadlock when a thread recurses on a readlock
//
Since we use a reader-preferring approach, we wait first for all readers to leave, and then all writers.
//
this also means that we must broadcast when the readers leave in order to give all the waiting writers a chance to wake up
//
The other way around could result in several writers acquiring the lock.
// new readers might still pass before some of the waiting writers, but then they'll just wait some more
if
(
this
->
readers_nb
>
0
)
{
// OTOH, if the new readers come, not broadcasting would let some writers wait forever
if
(
owner_id
==
CyObject_MANY_OWNERS
)
{
pthread_mutex_lock
(
&
(
CyLock
::
log_guard
));
printf
(
"Contention with several other reader threads detected while wlocking lock [%p] in thread #%d:
\n
"
"
\n
"
,
this
,
caller_id
);
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
));
}
}
while
(
this
->
readers_nb
>
0
)
{
while
(
this
->
readers_nb
>
0
)
{
pthread_cond_wait
(
&
this
->
wait_readers_depart
,
&
this
->
guard
);
pthread_cond_wait
(
&
this
->
readers_have_left
,
&
this
->
guard
);
}
if
(
this
->
write_count
>
0
)
{
pthread_mutex_lock
(
&
(
CyLock
::
log_guard
));
printf
(
"Contention with another writer detected while wlocking lock [%p] in thread #%d:
\n
"
" - lock was already wlocked by thread %d
\n
"
"
\n
"
,
this
,
caller_id
,
owner_id
);
pthread_mutex_unlock
(
&
(
CyLock
::
log_guard
));
}
}
while
(
this
->
write_count
>
0
)
{
while
(
this
->
write_count
>
0
)
{
pthread_cond_wait
(
&
this
->
w
ait_writer_depar
t
,
&
this
->
guard
);
pthread_cond_wait
(
&
this
->
w
riter_has_lef
t
,
&
this
->
guard
);
}
}
this
->
owner_id
=
caller_id
;
this
->
owner_id
=
caller_id
;
...
@@ -416,7 +447,7 @@ void RecursiveUpgradeableRWLock::wlock() {
...
@@ -416,7 +447,7 @@ void RecursiveUpgradeableRWLock::wlock() {
pthread_mutex_unlock
(
&
this
->
guard
);
pthread_mutex_unlock
(
&
this
->
guard
);
}
}
int
RecursiveUpgradeableRW
Lock
::
trywlock
()
{
int
Cy
Lock
::
trywlock
()
{
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
)
{
...
@@ -450,8 +481,7 @@ int RecursiveUpgradeableRWLock::trywlock() {
...
@@ -450,8 +481,7 @@ int RecursiveUpgradeableRWLock::trywlock() {
return
0
;
return
0
;
}
}
void
RecursiveUpgradeableRWLock
::
unwlock
()
{
void
CyLock
::
unwlock
()
{
pthread_mutex_lock
(
&
this
->
guard
);
pthread_mutex_lock
(
&
this
->
guard
);
if
(
--
this
->
write_count
==
0
)
{
if
(
--
this
->
write_count
==
0
)
{
if
(
this
->
readers_nb
==
0
)
{
if
(
this
->
readers_nb
==
0
)
{
...
@@ -460,109 +490,11 @@ void RecursiveUpgradeableRWLock::unwlock() {
...
@@ -460,109 +490,11 @@ void RecursiveUpgradeableRWLock::unwlock() {
// broadcast to wake up all the waiting readers, + maybe one waiting writer
// broadcast to wake up all the waiting readers, + maybe one waiting writer
// more efficient to count r waiting readers and w waiting writers and signal n + (w > 0) times
// more efficient to count r waiting readers and w waiting writers and signal n + (w > 0) times
pthread_cond_broadcast
(
&
this
->
wait_writer_depart
);
pthread_cond_broadcast
(
&
this
->
writer_has_left
);
}
pthread_mutex_unlock
(
&
this
->
guard
);
}
void
LogLock
::
rlock
()
{
pid_t
caller_id
=
syscall
(
SYS_gettid
);
if
(
this
->
owner_id
==
caller_id
)
{
++
this
->
readers_nb
;
return
;
}
pthread_mutex_lock
(
&
this
->
guard
);
if
(
this
->
write_count
>
0
)
{
pid_t
owner_id
=
this
->
owner_id
;
pthread_mutex_lock
(
&
(
LogLock
::
log_guard
));
printf
(
"Contention with a writer detected while rlocking lock [%p] in thread #%d:
\n
"
" - lock was already wlocked by thread %d
\n
"
"
\n
"
,
this
,
caller_id
,
owner_id
);
pthread_mutex_unlock
(
&
(
LogLock
::
log_guard
));
}
}
while
(
this
->
write_count
>
0
)
{
pthread_cond_wait
(
&
this
->
wait_writer_depart
,
&
this
->
guard
);
}
this
->
owner_id
=
this
->
readers_nb
++
?
CyObject_MANY_OWNERS
:
caller_id
;
pthread_mutex_unlock
(
&
this
->
guard
);
pthread_mutex_unlock
(
&
this
->
guard
);
}
}
void
LogLock
::
wlock
()
{
pid_t
caller_id
=
syscall
(
SYS_gettid
);
if
(
this
->
owner_id
==
caller_id
)
{
if
(
this
->
write_count
)
{
++
this
->
write_count
;
return
;
}
}
pthread_mutex_lock
(
&
this
->
guard
);
pid_t
owner_id
=
this
->
owner_id
;
if
(
owner_id
!=
caller_id
)
{
if
(
this
->
readers_nb
>
0
)
{
if
(
owner_id
==
CyObject_MANY_OWNERS
)
{
pthread_mutex_lock
(
&
(
LogLock
::
log_guard
));
printf
(
"Contention with several other reader threads detected while wlocking lock [%p] in thread #%d:
\n
"
"
\n
"
,
this
,
caller_id
);
pthread_mutex_unlock
(
&
(
LogLock
::
log_guard
));
}
else
{
pthread_mutex_lock
(
&
(
LogLock
::
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
(
&
(
LogLock
::
log_guard
));
}
}
while
(
this
->
readers_nb
>
0
)
{
pthread_cond_wait
(
&
this
->
wait_readers_depart
,
&
this
->
guard
);
}
if
(
this
->
write_count
>
0
)
{
pthread_mutex_lock
(
&
(
LogLock
::
log_guard
));
printf
(
"Contention with another writer detected while wlocking lock [%p] in thread #%d:
\n
"
" - lock was already wlocked by thread %d
\n
"
"
\n
"
,
this
,
caller_id
,
owner_id
);
pthread_mutex_unlock
(
&
(
LogLock
::
log_guard
));
}
while
(
this
->
write_count
>
0
)
{
pthread_cond_wait
(
&
this
->
wait_writer_depart
,
&
this
->
guard
);
}
this
->
owner_id
=
caller_id
;
}
this
->
write_count
=
1
;
pthread_mutex_unlock
(
&
this
->
guard
);
}
/*
/*
* Atomic counter increment and decrement implementation based on
* Atomic counter increment and decrement implementation based on
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment