Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tobias Decking
GHC
Commits
59c03ecb
Commit
59c03ecb
authored
Oct 19, 2006
by
Simon Marlow
Browse files
add pure spin locks
parent
fa4ee2f3
Changes
1
Hide whitespace changes
Inline
Side-by-side
includes/SMP.h
View file @
59c03ecb
...
...
@@ -22,10 +22,40 @@
#error Build options incompatible with THREADED_RTS.
#endif
/* ----------------------------------------------------------------------------
Atomic operations
------------------------------------------------------------------------- */
/*
* The atomic exchange operation: xchg(p,w) exchanges the value
* pointed to by p with the value w, returning the old value.
*
* Used for locking closures during updates (see lockClosure() below)
* and the MVar primops.
*/
INLINE_HEADER
StgWord
xchg
(
StgPtr
p
,
StgWord
w
);
/*
* XCHG - the atomic exchange instruction. Used for locking closures
* during updates (see lockClosure() below) and the MVar primops.
* Compare-and-swap. Atomically does this:
*
* cas(p,o,n) {
* r = *p;
* if (r == o) { *p = n };
* return r;
* }
*/
INLINE_HEADER
StgWord
cas
(
StgVolatilePtr
p
,
StgWord
o
,
StgWord
n
);
/*
* Prevents write operations from moving across this call in either
* direction.
*/
INLINE_HEADER
void
write_barrier
(
void
);
/* ----------------------------------------------------------------------------
Implementations
------------------------------------------------------------------------- */
/*
* NB: the xchg instruction is implicitly locked, so we do not need
* a lock prefix here.
*/
...
...
@@ -137,11 +167,12 @@ write_barrier(void) {
#endif
}
/*
/*
-----------------------------------------------------------------------------
* Locking/unlocking closures
*
* This is used primarily in the implementation of MVars.
*/
* -------------------------------------------------------------------------- */
#define SPIN_COUNT 4000
INLINE_HEADER
StgInfoTable
*
...
...
@@ -161,11 +192,100 @@ lockClosure(StgClosure *p)
INLINE_HEADER
void
unlockClosure
(
StgClosure
*
p
,
StgInfoTable
*
info
)
{
// This is a strictly ordered write, so we need a w
b
():
// This is a strictly ordered write, so we need a w
rite_barrier
():
write_barrier
();
p
->
header
.
info
=
info
;
}
/* -----------------------------------------------------------------------------
* Spin locks
*
* These are simple spin-only locks as opposed to Mutexes which
* probably spin for a while before blocking in the kernel. We use
* these when we are sure that all our threads are actively running on
* a CPU, eg. in the GC.
*
* TODO: measure whether we really need these, or whether Mutexes
* would do (and be a bit safer if a CPU becomes loaded).
* -------------------------------------------------------------------------- */
#if defined(DEBUG)
typedef
struct
StgSync_
{
StgWord32
lock
;
StgWord64
spin
;
// DEBUG version counts how much it spins
}
StgSync
;
#else
typedef
StgWord
StgSync
;
#endif
typedef
lnat
StgSyncCount
;
#if defined(DEBUG)
// Debug versions of spin locks maintain a spin count
// How to use:
// To use the debug veriosn of the spin locks, a debug version of the program
// can be run under a deugger with a break point on stat_exit. At exit time
// of the program one can examine the state the spin count counts of various
// spin locks to check for contention.
// acquire spin lock
INLINE_HEADER
void
acquireSpinLock
(
StgSync
*
p
)
{
StgWord32
r
=
0
;
do
{
p
->
spin
++
;
r
=
cas
((
StgVolatilePtr
)
&
(
p
->
lock
),
1
,
0
);
}
while
(
r
==
0
);
p
->
spin
--
;
}
// release spin lock
INLINE_HEADER
void
releaseSpinLock
(
StgSync
*
p
)
{
write_barrier
();
p
->
lock
=
1
;
}
// initialise spin lock
INLINE_HEADER
void
initSpinLock
(
StgSync
*
p
)
{
write_barrier
();
p
->
lock
=
1
;
p
->
spin
=
0
;
}
#else
// acquire spin lock
INLINE_HEADER
void
acquireSpinLock
(
StgSync
*
p
)
{
StgWord32
r
=
0
;
do
{
r
=
cas
((
StgVolatilePtr
)
p
,
1
,
0
);
}
while
(
r
==
0
);
}
// release spin lock
INLINE_HEADER
void
releaseSpinLock
(
StgSync
*
p
)
{
write_barrier
();
(
*
p
)
=
1
;
}
// init spin lock
INLINE_HEADER
void
initSpinLock
(
StgSync
*
p
)
{
write_barrier
();
(
*
p
)
=
1
;
}
#endif
/* DEBUG */
/* ---------------------------------------------------------------------- */
#else
/* !THREADED_RTS */
#define write_barrier()
/* nothing */
...
...
@@ -186,6 +306,15 @@ INLINE_HEADER void
unlockClosure
(
StgClosure
*
p
STG_UNUSED
,
StgInfoTable
*
info
STG_UNUSED
)
{
/* nothing */
}
INLINE_HEADER
void
acquireSpinLock
(
void
*
p
STG_UNUSED
)
{
/* nothing */
}
INLINE_HEADER
void
releaseSpinLock
(
void
*
p
STG_UNUSED
)
{
/* nothing */
}
INLINE_HEADER
void
initSpinLock
(
void
*
p
STG_UNUSED
)
{
/* nothing */
}
#endif
/* !THREADED_RTS */
// Handy specialised versions of lockClosure()/unlockClosure()
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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