Skip to content

Commit a068a8f

Browse files
committed
Add initial parking_lot module with raw_rwlock
1 parent c523076 commit a068a8f

File tree

5 files changed

+1218
-0
lines changed

5 files changed

+1218
-0
lines changed

src/libstd/sys_common/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub mod backtrace;
4545
pub mod condvar;
4646
pub mod io;
4747
pub mod mutex;
48+
pub mod parking_lot;
4849
pub mod parking_lot_core;
4950
pub mod poison;
5051
pub mod remutex;
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Copyright 2016 Amanieu d'Antras
2+
//
3+
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4+
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5+
// http://opensource.org/licenses/MIT>, at your option. This file may not be
6+
// copied, modified, or distributed except according to those terms.
7+
8+
use sync::atomic::AtomicUsize;
9+
10+
// Extension trait to add lock elision primitives to atomic types
11+
pub trait AtomicElisionExt {
12+
type IntType;
13+
14+
// Perform a compare_exchange and start a transaction
15+
fn elision_acquire(
16+
&self,
17+
current: Self::IntType,
18+
new: Self::IntType,
19+
) -> Result<Self::IntType, Self::IntType>;
20+
// Perform a compare_exchange and end a transaction
21+
fn elision_release(
22+
&self,
23+
current: Self::IntType,
24+
new: Self::IntType,
25+
) -> Result<Self::IntType, Self::IntType>;
26+
}
27+
28+
// Indicates whether the target architecture supports lock elision
29+
#[inline]
30+
pub fn have_elision() -> bool {
31+
cfg!(any(target_arch = "x86", target_arch = "x86_64"))
32+
}
33+
34+
// This implementation is never actually called because it is guarded by
35+
// have_elision().
36+
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
37+
impl AtomicElisionExt for AtomicUsize {
38+
type IntType = usize;
39+
40+
#[inline]
41+
fn elision_acquire(&self, _: usize, _: usize) -> Result<usize, usize> {
42+
unreachable!();
43+
}
44+
45+
#[inline]
46+
fn elision_release(&self, _: usize, _: usize) -> Result<usize, usize> {
47+
unreachable!();
48+
}
49+
}
50+
51+
#[cfg(target_arch = "x86")]
52+
impl AtomicElisionExt for AtomicUsize {
53+
type IntType = usize;
54+
55+
#[inline]
56+
fn elision_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
57+
unsafe {
58+
let prev: usize;
59+
asm!("xacquire; lock; cmpxchgl $2, $1"
60+
: "={eax}" (prev), "+*m" (self)
61+
: "r" (new), "{eax}" (current)
62+
: "memory"
63+
: "volatile");
64+
if prev == current {
65+
Ok(prev)
66+
} else {
67+
Err(prev)
68+
}
69+
}
70+
}
71+
72+
#[inline]
73+
fn elision_release(&self, current: usize, new: usize) -> Result<usize, usize> {
74+
unsafe {
75+
let prev: usize;
76+
asm!("xrelease; lock; cmpxchgl $2, $1"
77+
: "={eax}" (prev), "+*m" (self)
78+
: "r" (new), "{eax}" (current)
79+
: "memory"
80+
: "volatile");
81+
if prev == current {
82+
Ok(prev)
83+
} else {
84+
Err(prev)
85+
}
86+
}
87+
}
88+
}
89+
90+
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
91+
impl AtomicElisionExt for AtomicUsize {
92+
type IntType = usize;
93+
94+
#[inline]
95+
fn elision_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
96+
unsafe {
97+
let prev: usize;
98+
asm!("xacquire; lock; cmpxchgl $2, $1"
99+
: "={rax}" (prev), "+*m" (self)
100+
: "r" (new), "{rax}" (current)
101+
: "memory"
102+
: "volatile");
103+
if prev == current {
104+
Ok(prev)
105+
} else {
106+
Err(prev)
107+
}
108+
}
109+
}
110+
111+
#[inline]
112+
fn elision_release(&self, current: usize, new: usize) -> Result<usize, usize> {
113+
unsafe {
114+
let prev: usize;
115+
asm!("xrelease; lock; cmpxchgl $2, $1"
116+
: "={rax}" (prev), "+*m" (self)
117+
: "r" (new), "{rax}" (current)
118+
: "memory"
119+
: "volatile");
120+
if prev == current {
121+
Ok(prev)
122+
} else {
123+
Err(prev)
124+
}
125+
}
126+
}
127+
}
128+
129+
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
130+
impl AtomicElisionExt for AtomicUsize {
131+
type IntType = usize;
132+
133+
#[inline]
134+
fn elision_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
135+
unsafe {
136+
let prev: usize;
137+
asm!("xacquire; lock; cmpxchgq $2, $1"
138+
: "={rax}" (prev), "+*m" (self)
139+
: "r" (new), "{rax}" (current)
140+
: "memory"
141+
: "volatile");
142+
if prev == current {
143+
Ok(prev)
144+
} else {
145+
Err(prev)
146+
}
147+
}
148+
}
149+
150+
#[inline]
151+
fn elision_release(&self, current: usize, new: usize) -> Result<usize, usize> {
152+
unsafe {
153+
let prev: usize;
154+
asm!("xrelease; lock; cmpxchgq $2, $1"
155+
: "={rax}" (prev), "+*m" (self)
156+
: "r" (new), "{rax}" (current)
157+
: "memory"
158+
: "volatile");
159+
if prev == current {
160+
Ok(prev)
161+
} else {
162+
Err(prev)
163+
}
164+
}
165+
}
166+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
pub mod raw_rwlock;
3+
pub mod raw_mutex;
4+
pub mod elision;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 Amanieu d'Antras
2+
//
3+
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4+
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5+
// http://opensource.org/licenses/MIT>, at your option. This file may not be
6+
// copied, modified, or distributed except according to those terms.
7+
8+
type U8 = u8;
9+
use super::super::parking_lot_core::UnparkToken;
10+
11+
// UnparkToken used to indicate that that the target thread should attempt to
12+
// lock the mutex again as soon as it is unparked.
13+
pub const TOKEN_NORMAL: UnparkToken = UnparkToken(0);
14+
15+
// UnparkToken used to indicate that the mutex is being handed off to the target
16+
// thread directly without unlocking it.
17+
pub const TOKEN_HANDOFF: UnparkToken = UnparkToken(1);
18+
19+
const LOCKED_BIT: U8 = 1;
20+
const PARKED_BIT: U8 = 2;

0 commit comments

Comments
 (0)