Remove global test thread locking

With the recent changes in bootutil, now there is no need to lock the
test threads to run sequentially, so the global lock was removed. The
locking now happens to access resources such as flash, flash params,
simulator context, etc on a per thread basis. Some of the global
variables that were used by the simulator itself (FFI) were made into a
context struct passed in to invoke_go.

Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/sim/mcuboot-sys/src/api.rs b/sim/mcuboot-sys/src/api.rs
index 78a1bbd..f38d98e 100644
--- a/sim/mcuboot-sys/src/api.rs
+++ b/sim/mcuboot-sys/src/api.rs
@@ -1,104 +1,190 @@
 //! HAL api for MyNewt applications
 
-use simflash::{Result, Flash, FlashPtr};
-use lazy_static::lazy_static;
+use crate::area::CAreaDesc;
 use libc;
 use log::{Level, log_enabled, warn};
+use simflash::{Result, Flash, FlashPtr};
 use std::{
+    cell::RefCell,
     collections::HashMap,
     mem,
-    ops::Deref,
+    ptr,
     slice,
-    sync::Mutex,
 };
 
 /// A FlashMap maintain a table of [device_id -> Flash trait]
 pub type FlashMap = HashMap<u8, FlashPtr>;
 
-lazy_static! {
-    static ref FLASH: Mutex<FlashMap> = {
-        Mutex::new(HashMap::new())
-    };
-}
-
-struct FlashParams {
+pub struct FlashParamsStruct {
     align: u8,
     erased_val: u8,
 }
 
-lazy_static! {
-    static ref FLASH_PARAMS: Mutex<HashMap<u8, FlashParams>> = {
-        Mutex::new(HashMap::new())
-    };
+pub type FlashParams = HashMap<u8, FlashParamsStruct>;
+
+pub struct CAreaDescPtr {
+   pub ptr: *const CAreaDesc,
+}
+
+pub struct FlashContext {
+    flash_map: FlashMap,
+    flash_params: FlashParams,
+    flash_areas: CAreaDescPtr,
+}
+
+impl FlashContext {
+    pub fn new() -> FlashContext {
+        FlashContext {
+            flash_map: HashMap::new(),
+            flash_params: HashMap::new(),
+            flash_areas: CAreaDescPtr{ptr: ptr::null()},
+        }
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct CSimContext {
+    pub flash_counter: libc::c_int,
+    pub jumped: libc::c_int,
+    pub c_asserts: u8,
+    pub c_catch_asserts: u8,
+    // NOTE: Always leave boot_jmpbuf declaration at the end; this should
+    // store a "jmp_buf" which is arch specific and not defined by libc crate.
+    // The size below is enough to store data on a x86_64 machine.
+    pub boot_jmpbuf: [u64; 16],
+}
+
+pub struct CSimContextPtr {
+   pub ptr: *const CSimContext,
+}
+
+impl CSimContextPtr {
+    pub fn new() -> CSimContextPtr {
+        CSimContextPtr {
+            ptr: ptr::null(),
+        }
+    }
+}
+
+thread_local! {
+    pub static THREAD_CTX: RefCell<FlashContext> = RefCell::new(FlashContext::new());
+    pub static SIM_CTX: RefCell<CSimContextPtr> = RefCell::new(CSimContextPtr::new());
 }
 
 // Set the flash device to be used by the simulation.  The pointer is unsafely stashed away.
 pub unsafe fn set_flash(dev_id: u8, dev: &mut dyn Flash) {
-    let mut flash_params = FLASH_PARAMS.lock().unwrap();
-    flash_params.insert(dev_id, FlashParams {
-        align: dev.align() as u8,
-        erased_val: dev.erased_val(),
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow_mut().flash_params.insert(dev_id, FlashParamsStruct {
+            align: dev.align() as u8,
+            erased_val: dev.erased_val(),
+        });
+        let dev: &'static mut dyn Flash = mem::transmute(dev);
+        ctx.borrow_mut().flash_map.insert(
+            dev_id, FlashPtr{ptr: dev as *mut dyn Flash});
     });
-
-    let dev: &'static mut dyn Flash = mem::transmute(dev);
-    let mut flash = FLASH.lock().unwrap();
-    flash.insert(dev_id, FlashPtr{ptr: dev as *mut dyn Flash});
 }
 
 pub unsafe fn clear_flash(dev_id: u8) {
-    let mut flash = FLASH.lock().unwrap();
-    flash.remove(&dev_id);
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow_mut().flash_map.remove(&dev_id);
+    });
 }
 
 // This isn't meant to call directly, but by a wrapper.
 
 #[no_mangle]
+pub extern fn sim_get_flash_areas() -> *const CAreaDesc {
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow().flash_areas.ptr
+    })
+}
+
+#[no_mangle]
+pub extern fn sim_set_flash_areas(areas: *const CAreaDesc) {
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow_mut().flash_areas.ptr = areas;
+    });
+}
+
+#[no_mangle]
+pub extern fn sim_reset_flash_areas() {
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow_mut().flash_areas.ptr = ptr::null();
+    });
+}
+
+#[no_mangle]
+pub extern fn sim_get_context() -> *const CSimContext {
+    SIM_CTX.with(|ctx| {
+        ctx.borrow().ptr
+    })
+}
+
+#[no_mangle]
+pub extern fn sim_set_context(ptr: *const CSimContext) {
+    SIM_CTX.with(|ctx| {
+        ctx.borrow_mut().ptr = ptr;
+    });
+}
+
+#[no_mangle]
+pub extern fn sim_reset_context() {
+    SIM_CTX.with(|ctx| {
+        ctx.borrow_mut().ptr = ptr::null();
+    });
+}
+
+#[no_mangle]
 pub extern fn sim_flash_erase(dev_id: u8, offset: u32, size: u32) -> libc::c_int {
-    if let Ok(guard) = FLASH.lock() {
-        if let Some(flash) = guard.deref().get(&dev_id) {
+    let mut rc: libc::c_int = -19;
+    THREAD_CTX.with(|ctx| {
+        if let Some(flash) = ctx.borrow().flash_map.get(&dev_id) {
             let dev = unsafe { &mut *(flash.ptr) };
-            return map_err(dev.erase(offset as usize, size as usize));
+            rc = map_err(dev.erase(offset as usize, size as usize));
         }
-    }
-    -19
+    });
+    rc
 }
 
 #[no_mangle]
 pub extern fn sim_flash_read(dev_id: u8, offset: u32, dest: *mut u8, size: u32) -> libc::c_int {
-    if let Ok(guard) = FLASH.lock() {
-        if let Some(flash) = guard.deref().get(&dev_id) {
+    let mut rc: libc::c_int = -19;
+    THREAD_CTX.with(|ctx| {
+        if let Some(flash) = ctx.borrow().flash_map.get(&dev_id) {
             let mut buf: &mut[u8] = unsafe { slice::from_raw_parts_mut(dest, size as usize) };
             let dev = unsafe { &mut *(flash.ptr) };
-            return map_err(dev.read(offset as usize, &mut buf));
+            rc = map_err(dev.read(offset as usize, &mut buf));
         }
-    }
-    -19
+    });
+    rc
 }
 
 #[no_mangle]
 pub extern fn sim_flash_write(dev_id: u8, offset: u32, src: *const u8, size: u32) -> libc::c_int {
-    if let Ok(guard) = FLASH.lock() {
-        if let Some(flash) = guard.deref().get(&dev_id) {
+    let mut rc: libc::c_int = -19;
+    THREAD_CTX.with(|ctx| {
+        if let Some(flash) = ctx.borrow().flash_map.get(&dev_id) {
             let buf: &[u8] = unsafe { slice::from_raw_parts(src, size as usize) };
             let dev = unsafe { &mut *(flash.ptr) };
-            return map_err(dev.write(offset as usize, &buf));
+            rc = map_err(dev.write(offset as usize, &buf));
         }
-    }
-    -19
+    });
+    rc
 }
 
 #[no_mangle]
 pub extern fn sim_flash_align(id: u8) -> u8 {
-    let flash_params = FLASH_PARAMS.lock().unwrap();
-    let params = flash_params.get(&id).unwrap();
-    params.align
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow().flash_params.get(&id).unwrap().align
+    })
 }
 
 #[no_mangle]
 pub extern fn sim_flash_erased_val(id: u8) -> u8 {
-    let flash_params = FLASH_PARAMS.lock().unwrap();
-    let params = flash_params.get(&id).unwrap();
-    params.erased_val
+    THREAD_CTX.with(|ctx| {
+        ctx.borrow().flash_params.get(&id).unwrap().erased_val
+    })
 }
 
 fn map_err(err: Result<()>) -> libc::c_int {