@@ -11,17 +11,18 @@ use crate::symbolize::ResolveWhat;
11
11
use crate :: types:: BytesOrWideString ;
12
12
use crate :: SymbolName ;
13
13
use addr2line:: gimli;
14
- use core:: cell:: RefCell ;
15
14
use core:: convert:: TryFrom ;
16
15
use core:: mem;
17
16
use core:: u32;
18
17
use findshlibs:: { self , Segment , SharedLibrary } ;
18
+ use lazy_static:: lazy_static;
19
19
use libc:: c_void;
20
20
use memmap:: Mmap ;
21
21
use std:: env;
22
22
use std:: fs:: File ;
23
23
use std:: path:: { Path , PathBuf } ;
24
24
use std:: prelude:: v1:: * ;
25
+ use std:: sync:: Mutex ;
25
26
26
27
const MAPPINGS_CACHE_SIZE : usize = 4 ;
27
28
@@ -329,57 +330,62 @@ impl Mapping {
329
330
}
330
331
}
331
332
332
- // A very small, very simple LRU cache for debug info mappings.
333
- //
334
- // The hit rate should be very high, since the typical stack doesn't cross
335
- // between many shared libraries.
336
- //
337
- // The `addr2line::Context` structures are pretty expensive to create. Its
338
- // cost is expected to be amortized by subsequent `locate` queries, which
339
- // leverage the structures built when constructing `addr2line::Context`s to
340
- // get nice speedups. If we didn't have this cache, that amortization would
341
- // never happen, and symbolicating backtraces would be ssssllllooooowwww.
342
- static MAPPINGS_CACHE : RefCell < Vec < ( PathBuf , Mapping ) > >
343
- = RefCell :: new ( Vec :: with_capacity ( MAPPINGS_CACHE_SIZE ) ) ;
333
+ lazy_static ! {
334
+ // A very small, very simple LRU cache for debug info mappings.
335
+ //
336
+ // The hit rate should be very high, since the typical stack doesn't cross
337
+ // between many shared libraries.
338
+ //
339
+ // The `addr2line::Context` structures are pretty expensive to create. Its
340
+ // cost is expected to be amortized by subsequent `locate` queries, which
341
+ // leverage the structures built when constructing `addr2line::Context`s to
342
+ // get nice speedups. If we didn't have this cache, that amortization would
343
+ // never happen, and symbolicating backtraces would be ssssllllooooowwww.
344
+ // static MAPPINGS_CACHE: RefCell<Vec<(PathBuf, Mapping)>> = RefCell::new(Vec::with_capacity(MAPPINGS_CACHE_SIZE));
345
+ static ref MAPPINGS_CACHE : Mutex <Vec <( PathBuf , Mapping ) >> = Mutex :: new( Vec :: with_capacity( MAPPINGS_CACHE_SIZE ) ) ;
346
+ }
344
347
345
348
pub fn clear_symbol_cache ( ) {
346
- MAPPINGS_CACHE . borrow_mut ( ) . clear ( )
349
+ if let Ok ( mut cache) = MAPPINGS_CACHE . lock ( ) {
350
+ cache. clear ( ) ;
351
+ }
347
352
}
348
353
349
354
fn with_mapping_for_path < F > ( path : PathBuf , f : F )
350
355
where
351
356
F : FnMut ( & Context < ' _ > ) ,
352
357
{
353
- let mut cache = MAPPINGS_CACHE . borrow_mut ( ) ;
358
+ if let Ok ( mut cache) = MAPPINGS_CACHE . lock ( ) {
354
359
355
- let idx = cache. iter ( ) . position ( |& ( ref p, _) | p == & path) ;
360
+ let idx = cache. iter ( ) . position ( |& ( ref p, _) | p == & path) ;
356
361
357
- // Invariant: after this conditional completes without early returning
358
- // from an error, the cache entry for this path is at index 0.
362
+ // Invariant: after this conditional completes without early returning
363
+ // from an error, the cache entry for this path is at index 0.
359
364
360
- if let Some ( idx) = idx {
361
- // When the mapping is already in the cache, move it to the front.
362
- if idx != 0 {
363
- let entry = cache. remove ( idx) ;
364
- cache. insert ( 0 , entry) ;
365
- }
366
- } else {
367
- // When the mapping is not in the cache, create a new mapping,
368
- // insert it into the front of the cache, and evict the oldest cache
369
- // entry if necessary.
370
- let mapping = match Mapping :: new ( & path) {
371
- None => return ,
372
- Some ( m) => m,
373
- } ;
365
+ if let Some ( idx) = idx {
366
+ // When the mapping is already in the cache, move it to the front.
367
+ if idx != 0 {
368
+ let entry = cache. remove ( idx) ;
369
+ cache. insert ( 0 , entry) ;
370
+ }
371
+ } else {
372
+ // When the mapping is not in the cache, create a new mapping,
373
+ // insert it into the front of the cache, and evict the oldest cache
374
+ // entry if necessary.
375
+ let mapping = match Mapping :: new ( & path) {
376
+ None => return ,
377
+ Some ( m) => m,
378
+ } ;
374
379
375
- if cache. len ( ) == MAPPINGS_CACHE_SIZE {
376
- cache. pop ( ) ;
380
+ if cache. len ( ) == MAPPINGS_CACHE_SIZE {
381
+ cache. pop ( ) ;
382
+ }
383
+
384
+ cache. insert ( 0 , ( path, mapping) ) ;
377
385
}
378
386
379
- cache. insert ( 0 , ( path , mapping ) ) ;
387
+ cache[ 0 ] . 1 . rent ( f ) ;
380
388
}
381
-
382
- cache[ 0 ] . 1 . rent ( f) ;
383
389
}
384
390
385
391
pub unsafe fn resolve ( what : ResolveWhat , cb : & mut FnMut ( & super :: Symbol ) ) {
0 commit comments