@@ -4,6 +4,8 @@ use rand::Rng;
4
4
5
5
use rustc_target:: abi:: { Align , Size } ;
6
6
7
+ use crate :: concurrency:: VClock ;
8
+
7
9
const MAX_POOL_SIZE : usize = 64 ;
8
10
9
11
// Just use fair coins, until we have evidence that other numbers are better.
@@ -21,42 +23,57 @@ pub struct ReusePool {
21
23
///
22
24
/// Each of these maps has at most MAX_POOL_SIZE elements, and since alignment is limited to
23
25
/// less than 64 different possible value, that bounds the overall size of the pool.
24
- pool : Vec < Vec < ( u64 , Size ) > > ,
26
+ ///
27
+ /// We also store the clock from the thread that donated this pool element,
28
+ /// to ensure synchronization with the thread that picks up this address.
29
+ pool : Vec < Vec < ( u64 , Size , VClock ) > > ,
25
30
}
26
31
27
32
impl ReusePool {
28
33
pub fn new ( ) -> Self {
29
34
ReusePool { pool : vec ! [ ] }
30
35
}
31
36
32
- fn subpool ( & mut self , align : Align ) -> & mut Vec < ( u64 , Size ) > {
37
+ fn subpool ( & mut self , align : Align ) -> & mut Vec < ( u64 , Size , VClock ) > {
33
38
let pool_idx: usize = align. bytes ( ) . trailing_zeros ( ) . try_into ( ) . unwrap ( ) ;
34
39
if self . pool . len ( ) <= pool_idx {
35
40
self . pool . resize ( pool_idx + 1 , Vec :: new ( ) ) ;
36
41
}
37
42
& mut self . pool [ pool_idx]
38
43
}
39
44
40
- pub fn add_addr ( & mut self , rng : & mut impl Rng , addr : u64 , size : Size , align : Align ) {
45
+ pub fn add_addr (
46
+ & mut self ,
47
+ rng : & mut impl Rng ,
48
+ addr : u64 ,
49
+ size : Size ,
50
+ align : Align ,
51
+ clock : impl FnOnce ( ) -> VClock ,
52
+ ) {
41
53
// Let's see if we even want to remember this address.
42
54
if !rng. gen_bool ( ADDR_REMEMBER_CHANCE ) {
43
55
return ;
44
56
}
45
57
// Determine the pool to add this to, and where in the pool to put it.
46
58
let subpool = self . subpool ( align) ;
47
- let pos = subpool. partition_point ( |( _addr, other_size) | * other_size < size) ;
59
+ let pos = subpool. partition_point ( |( _addr, other_size, _ ) | * other_size < size) ;
48
60
// Make sure the pool does not grow too big.
49
61
if subpool. len ( ) >= MAX_POOL_SIZE {
50
62
// Pool full. Replace existing element, or last one if this would be even bigger.
51
63
let clamped_pos = pos. min ( subpool. len ( ) - 1 ) ;
52
- subpool[ clamped_pos] = ( addr, size) ;
64
+ subpool[ clamped_pos] = ( addr, size, clock ( ) ) ;
53
65
return ;
54
66
}
55
67
// Add address to pool, at the right position.
56
- subpool. insert ( pos, ( addr, size) ) ;
68
+ subpool. insert ( pos, ( addr, size, clock ( ) ) ) ;
57
69
}
58
70
59
- pub fn take_addr ( & mut self , rng : & mut impl Rng , size : Size , align : Align ) -> Option < u64 > {
71
+ pub fn take_addr (
72
+ & mut self ,
73
+ rng : & mut impl Rng ,
74
+ size : Size ,
75
+ align : Align ,
76
+ ) -> Option < ( u64 , VClock ) > {
60
77
// Determine whether we'll even attempt a reuse.
61
78
if !rng. gen_bool ( ADDR_TAKE_CHANCE ) {
62
79
return None ;
@@ -65,9 +82,9 @@ impl ReusePool {
65
82
let subpool = self . subpool ( align) ;
66
83
// Let's see if we can find something of the right size. We want to find the full range of
67
84
// such items, beginning with the first, so we can't use `binary_search_by_key`.
68
- let begin = subpool. partition_point ( |( _addr, other_size) | * other_size < size) ;
85
+ let begin = subpool. partition_point ( |( _addr, other_size, _ ) | * other_size < size) ;
69
86
let mut end = begin;
70
- while let Some ( ( _addr, other_size) ) = subpool. get ( end) {
87
+ while let Some ( ( _addr, other_size, _ ) ) = subpool. get ( end) {
71
88
if * other_size != size {
72
89
break ;
73
90
}
@@ -80,8 +97,8 @@ impl ReusePool {
80
97
// Pick a random element with the desired size.
81
98
let idx = rng. gen_range ( begin..end) ;
82
99
// Remove it from the pool and return.
83
- let ( chosen_addr, chosen_size) = subpool. remove ( idx) ;
100
+ let ( chosen_addr, chosen_size, clock ) = subpool. remove ( idx) ;
84
101
debug_assert ! ( chosen_size >= size && chosen_addr % align. bytes( ) == 0 ) ;
85
- Some ( chosen_addr)
102
+ Some ( ( chosen_addr, clock ) )
86
103
}
87
104
}
0 commit comments