diff --git a/context/mod.rs b/context/mod.rs
index 8e4f37d2a53f91edcb3f876003bbb778f46f5b40..1dde2eb70ecf4af7c1c8b8eca68595e6e31240fc 100644
--- a/context/mod.rs
+++ b/context/mod.rs
@@ -1,22 +1,52 @@
 //! Context management
 
+use alloc::arc::Arc;
+use collections::{BTreeMap, Vec};
+use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
+
 /// File operations
 pub mod file;
 
-/// Context list
-pub static mut CONTEXT: Context = Context::new();
+/// Maximum context files
+pub const CONTEXT_MAX_FILES: usize = 65536;
+
+/// Context ID
+pub type ContextId = u16;
+
+/// Context list type
+pub type ContextList = BTreeMap<ContextId, Arc<RwLock<Context>>>;
+
+/// Contexts list
+static CONTEXTS: Once<RwLock<ContextList>> = Once::new();
+
+/// Initialize contexts, called if needed
+fn init_contexts() -> RwLock<ContextList> {
+    let mut map: ContextList = BTreeMap::new();
+    map.insert(0, Arc::new(RwLock::new(Context::new())));
+    RwLock::new(map)
+}
+
+/// Get the global schemes list, const
+pub fn contexts() -> RwLockReadGuard<'static, ContextList> {
+    CONTEXTS.call_once(init_contexts).read()
+}
+
+/// Get the global schemes list, mutable
+pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
+    CONTEXTS.call_once(init_contexts).write()
+}
 
 /// A context, which identifies either a process or a thread
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
 pub struct Context {
     /// The open files in the scheme
-    pub files: [Option<file::File>; 32]
+    pub files: Vec<Option<file::File>>
 }
 
 impl Context {
-    pub const fn new() -> Context {
+    pub fn new() -> Context {
         Context {
-            files: [None; 32]
+            files: Vec::new()
         }
     }
 
@@ -29,6 +59,12 @@ impl Context {
                 return Some(i);
             }
         }
-        None
+        let len = self.files.len();
+        if len < CONTEXT_MAX_FILES {
+            self.files.push(Some(file));
+            Some(len)
+        } else {
+            None
+        }
     }
 }
diff --git a/scheme/mod.rs b/scheme/mod.rs
index 75b3eb645c8e6a6af5565d55e9d112ef88a26d98..d01931c461ff909351e7c39e43d8b47b6c94f767 100644
--- a/scheme/mod.rs
+++ b/scheme/mod.rs
@@ -20,21 +20,25 @@ use self::debug::DebugScheme;
 /// Debug scheme
 pub mod debug;
 
+/// Scheme list type
 pub type SchemeList = BTreeMap<Box<[u8]>, Arc<Mutex<Box<Scheme + Send>>>>;
 
 /// Schemes list
 static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
 
+/// Initialize schemes, called if needed
 fn init_schemes() -> RwLock<SchemeList> {
     let mut map: SchemeList = BTreeMap::new();
     map.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme))));
     RwLock::new(map)
 }
 
+/// Get the global schemes list, const
 pub fn schemes() -> RwLockReadGuard<'static, SchemeList> {
     SCHEMES.call_once(init_schemes).read()
 }
 
+/// Get the global schemes list, mutable
 pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> {
     SCHEMES.call_once(init_schemes).write()
 }
diff --git a/syscall/fs.rs b/syscall/fs.rs
index 2ded85871ab2d60f584dc432c2ac5ca5f29ff77e..e0e4a648b2a2e34176fba337802ff7685a91a259 100644
--- a/syscall/fs.rs
+++ b/syscall/fs.rs
@@ -1,5 +1,6 @@
 //! Filesystem syscalls
 
+use context;
 use scheme;
 
 use super::{Error, Result};
@@ -7,22 +8,32 @@ use super::{Error, Result};
 /// Read syscall
 pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
     println!("Read {}: {}", fd, buf.len());
-    if let Some(file) = unsafe { &mut ::context::CONTEXT }.files.get(fd) {
-        println!("{:?}", file);
-        Ok(0)
+    if let Some(context_lock) = context::contexts().get(&0) {
+        let context = context_lock.read();
+        if let Some(file) = context.files.get(fd) {
+            println!("{:?}", file);
+            Ok(0)
+        } else {
+            Err(Error::BadFile)
+        }
     } else {
-        Err(Error::BadFile)
+        Err(Error::NoProcess)
     }
 }
 
 /// Write syscall
 pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
     println!("Write {}: {}", fd, buf.len());
-    if let Some(file) = unsafe { &mut ::context::CONTEXT }.files.get(fd) {
-        println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
-        Ok(buf.len())
+    if let Some(context_lock) = context::contexts().get(&0) {
+        let context = context_lock.read();
+        if let Some(file) = context.files.get(fd) {
+            println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
+            Ok(buf.len())
+        } else {
+            Err(Error::BadFile)
+        }
     } else {
-        Err(Error::BadFile)
+        Err(Error::NoProcess)
     }
 }
 
@@ -46,13 +57,18 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
         }
     }?;
 
-    if let Some(fd) = unsafe { &mut ::context::CONTEXT }.add_file(::context::file::File {
-        scheme: 0,
-        number: file
-    }) {
-        Ok(fd)
+    if let Some(context_lock) = context::contexts().get(&0) {
+        let mut context = context_lock.write();
+        if let Some(fd) = context.add_file(::context::file::File {
+            scheme: 0,
+            number: file
+        }) {
+            Ok(fd)
+        } else {
+            Err(Error::TooManyFiles)
+        }
     } else {
-        Err(Error::TooManyFiles)
+        Err(Error::NoProcess)
     }
 }
 
diff --git a/syscall/mod.rs b/syscall/mod.rs
index 1cf0f5896a562d1fe74038f58830796844f530a0..df9b6d33131b07a8c1af2587ffca55a7fa522208 100644
--- a/syscall/mod.rs
+++ b/syscall/mod.rs
@@ -53,6 +53,8 @@ pub enum Error {
     NotPermitted,
     /// No such file or directory
     NoEntry,
+    /// No such process
+    NoProcess,
     /// Bad file number
     BadFile,
     /// Invalid argument
@@ -70,6 +72,7 @@ impl From<Error> for usize {
         match err {
             Error::NotPermitted => 1,
             Error::NoEntry => 2,
+            Error::NoProcess => 3,
             Error::BadFile => 9,
             Error::InvalidValue => 22,
             Error::TooManyFiles => 24,
diff --git a/tests/mod.rs b/tests/mod.rs
index 67e13c94a402e8177f2288655cfe7a3c653ef97c..3b92c184e3a178dbe1637a250b39fdd8e2474a60 100644
--- a/tests/mod.rs
+++ b/tests/mod.rs
@@ -1,16 +1,5 @@
-use arch::interrupt::{enable_interrupts, halt};
-
 use syscall::{self, Error};
 
-/// Test halting
-#[test]
-fn halt_with_interrupts() {
-    unsafe {
-        //enable_interrupts();
-        //halt();
-    }
-}
-
 /// Test stdio
 #[test]
 fn stdio() {