Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
e89137ce
Commit
e89137ce
authored
9 years ago
by
Torvald Riegel
Committed by
Torvald Riegel
9 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
libitm: Fix seq-cst MOs/fences in rwlock.
From-SVN: r232353
parent
d6683aec
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
33 additions
and
26 deletions
+33
-26
libitm/ChangeLog
+6
-0
libitm/beginend.cc
+4
-2
libitm/config/linux/rwlock.cc
+23
-24
No files found.
libitm/ChangeLog
View file @
e89137ce
2016-01-13 Torvald Riegel <triegel@redhat.com>
* beginend.cc (gtm_thread::trycommit): Fix seq_cst fences.
* config/linux/rwlock.cc (gtm_rwlock::write_lock_generic): Likewise.
(gtm_rwlock::write_unlock): Likewise.
2016-01-13 Richard Henderson <rth@redhat.com>
* Makefile.am (libitm_la_SOURCES) [ARCH_AARCH64]: Add vect128.cc
...
...
This diff is collapsed.
Click to expand it.
libitm/beginend.cc
View file @
e89137ce
...
...
@@ -619,8 +619,10 @@ GTM::gtm_thread::trycommit ()
// acquisitions). This ensures that if we read prior to other
// reader transactions setting their shared_state to 0, then those
// readers will observe our updates. We can reuse the seq_cst fence
// in serial_lock.read_unlock() however, so we don't need another
// one here.
// in serial_lock.read_unlock() if we performed that; if not, we
// issue the fence.
if
(
do_read_unlock
)
atomic_thread_fence
(
memory_order_seq_cst
);
// TODO Don't just spin but also block using cond vars / futexes
// here. Should probably be integrated with the serial lock code.
for
(
gtm_thread
*
it
=
gtm_thread
::
list_of_threads
;
it
!=
0
;
...
...
This diff is collapsed.
Click to expand it.
libitm/config/linux/rwlock.cc
View file @
e89137ce
...
...
@@ -122,9 +122,10 @@ gtm_rwlock::read_lock (gtm_thread *tx)
bool
gtm_rwlock
::
write_lock_generic
(
gtm_thread
*
tx
)
{
// Try to acquire the write lock.
// Try to acquire the write lock. Relaxed MO is fine because of the
// additional fence below.
int
w
=
0
;
if
(
unlikely
(
!
writers
.
compare_exchange_strong
(
w
,
1
)))
if
(
unlikely
(
!
writers
.
compare_exchange_strong
(
w
,
1
,
memory_order_relaxed
)))
{
// If this is an upgrade, we must not wait for other writers or
// upgrades.
...
...
@@ -135,18 +136,20 @@ gtm_rwlock::write_lock_generic (gtm_thread *tx)
// switch to contended mode. We need seq_cst memory order to make the
// Dekker-style synchronization work.
if
(
w
!=
2
)
w
=
writers
.
exchange
(
2
);
w
=
writers
.
exchange
(
2
,
memory_order_relaxed
);
while
(
w
!=
0
)
{
futex_wait
(
&
writers
,
2
);
w
=
writers
.
exchange
(
2
);
w
=
writers
.
exchange
(
2
,
memory_order_relaxed
);
}
}
// This fence is both required for the Dekker-like synchronization we do
// here and is the acquire MO required to make us synchronize-with prior
// writers.
atomic_thread_fence
(
memory_order_seq_cst
);
// We have acquired the writer side of the R/W lock. Now wait for any
// readers that might still be active.
// We don't need an extra barrier here because the CAS and the xchg
// operations have full barrier semantics already.
// TODO In the worst case, this requires one wait/wake pair for each
// active reader. Reduce this!
for
(
gtm_thread
*
it
=
gtm_thread
::
list_of_threads
;
it
!=
0
;
...
...
@@ -259,28 +262,24 @@ gtm_rwlock::read_unlock (gtm_thread *tx)
void
gtm_rwlock
::
write_unlock
()
{
//
This needs to have seq_cst memory order
.
if
(
writers
.
fetch_sub
(
1
)
==
2
)
//
Release MO so that we synchronize with subsequent writers
.
if
(
writers
.
exchange
(
0
,
memory_order_release
)
==
2
)
{
// There might be waiting writers, so wake them.
writers
.
store
(
0
,
memory_order_relaxed
);
if
(
futex_wake
(
&
writers
,
1
)
==
0
)
{
// If we did not wake any waiting writers, we might indeed be the
// last writer (this can happen because write_lock_generic()
// exchanges 0 or 1 to 2 and thus might go to contended mode even if
// no other thread holds the write lock currently). Therefore, we
// have to wake up readers here as well. Execute a barrier after
// the previous relaxed reset of writers (Dekker-style), and fall
// through to the normal reader wake-up code.
atomic_thread_fence
(
memory_order_seq_cst
);
}
else
// There might be waiting writers, so wake them. If we woke any thread,
// we assume it to indeed be a writer; waiting writers will never give
// up, so we can assume that they will take care of anything else such
// as waking readers.
if
(
futex_wake
(
&
writers
,
1
)
>
0
)
return
;
// If we did not wake any waiting writers, we might indeed be the last
// writer (this can happen because write_lock_generic() exchanges 0 or 1
// to 2 and thus might go to contended mode even if no other thread
// holds the write lock currently). Therefore, we have to fall through
// to the normal reader wake-up code.
}
// This fence is required because we do Dekker-like synchronization here.
atomic_thread_fence
(
memory_order_seq_cst
);
// No waiting writers, so wake up all waiting readers.
// Because the fetch_and_sub is a full barrier already, we don't need
// another barrier here (as in read_unlock()).
if
(
readers
.
load
(
memory_order_relaxed
)
>
0
)
{
// No additional barrier needed here. The previous load must be in
...
...
This diff is collapsed.
Click to expand it.
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