From 538ca49ee2de79c0f53b29782754778210671a9f Mon Sep 17 00:00:00 2001
From: jD91mZM2 <me@krake.one>
Date: Fri, 26 Jul 2019 12:23:21 +0200
Subject: [PATCH] Suggestion: Switch to bitflags

---
 Cargo.lock             |  3 +++
 src/context/context.rs |  4 ++--
 src/event.rs           | 23 +++++++++----------
 src/ptrace.rs          | 28 +++++++++++------------
 src/scheme/debug.rs    |  6 ++---
 src/scheme/irq.rs      |  6 ++---
 src/scheme/itimer.rs   |  6 ++---
 src/scheme/memory.rs   |  8 +++----
 src/scheme/pipe.rs     |  6 ++---
 src/scheme/proc.rs     | 11 +++++-----
 src/scheme/root.rs     |  4 ++--
 src/scheme/time.rs     |  6 ++---
 src/scheme/user.rs     | 20 ++++++++---------
 src/syscall/driver.rs  | 12 +++++-----
 src/syscall/fs.rs      |  4 ++--
 src/syscall/mod.rs     | 10 +++++----
 src/syscall/process.rs | 50 +++++++++++++++++++++---------------------
 syscall                |  2 +-
 18 files changed, 108 insertions(+), 101 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 48faff9c..a9cc12c2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -278,6 +278,9 @@ dependencies = [
 [[package]]
 name = "redox_syscall"
 version = "0.1.56"
+dependencies = [
+ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "regex"
diff --git a/src/context/context.rs b/src/context/context.rs
index 0a0f1869..216726e5 100644
--- a/src/context/context.rs
+++ b/src/context/context.rs
@@ -16,7 +16,7 @@ use crate::ipi::{ipi, IpiKind, IpiTarget};
 use crate::scheme::{SchemeNamespace, FileHandle};
 use crate::sync::WaitMap;
 use crate::syscall::data::SigAction;
-use crate::syscall::flag::SIG_DFL;
+use crate::syscall::flag::{SIG_DFL, SigActionFlags};
 
 /// Unique identifier for a context (i.e. `pid`).
 use ::core::sync::atomic::AtomicUsize;
@@ -222,7 +222,7 @@ impl Context {
                 SigAction {
                     sa_handler: unsafe { mem::transmute(SIG_DFL) },
                     sa_mask: [0; 2],
-                    sa_flags: 0,
+                    sa_flags: SigActionFlags::empty(),
                 },
                 0
             ); 128])),
diff --git a/src/event.rs b/src/event.rs
index 7a7d25e0..4eba3be2 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -8,6 +8,7 @@ use crate::scheme::{self, SchemeId};
 use crate::sync::WaitQueue;
 use crate::syscall::data::Event;
 use crate::syscall::error::{Error, Result, EBADF, EINTR, ESRCH};
+use crate::syscall::flag::EventFlags;
 
 int_like!(EventQueueId, AtomicEventQueueId, usize, AtomicUsize);
 
@@ -53,7 +54,7 @@ impl EventQueue {
             );
 
             let flags = sync(RegKey { scheme, number })?;
-            if flags > 0 {
+            if !flags.is_empty() {
                 trigger(scheme, number, flags);
             }
         }
@@ -100,10 +101,10 @@ pub struct RegKey {
 pub struct QueueKey {
     pub queue: EventQueueId,
     pub id: usize,
-    pub data: usize
+    pub data: usize,
 }
 
-type Registry = BTreeMap<RegKey, BTreeMap<QueueKey, usize>>;
+type Registry = BTreeMap<RegKey, BTreeMap<QueueKey, EventFlags>>;
 
 static REGISTRY: Once<RwLock<Registry>> = Once::new();
 
@@ -122,28 +123,28 @@ pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> {
     REGISTRY.call_once(init_registry).write()
 }
 
-pub fn register(reg_key: RegKey, queue_key: QueueKey, flags: usize) {
+pub fn register(reg_key: RegKey, queue_key: QueueKey, flags: EventFlags) {
     let mut registry = registry_mut();
 
     let entry = registry.entry(reg_key).or_insert_with(|| {
         BTreeMap::new()
     });
 
-    if flags == 0 {
+    if flags.is_empty() {
         entry.remove(&queue_key);
     } else {
         entry.insert(queue_key, flags);
     }
 }
 
-pub fn sync(reg_key: RegKey) -> Result<usize> {
-    let mut flags = 0;
+pub fn sync(reg_key: RegKey) -> Result<EventFlags> {
+    let mut flags = EventFlags::empty();
 
     {
         let registry = registry();
 
         if let Some(queue_list) = registry.get(&reg_key) {
-            for (_queue_key, queue_flags) in queue_list.iter() {
+            for (_queue_key, &queue_flags) in queue_list.iter() {
                 flags |= queue_flags;
             }
         }
@@ -169,13 +170,13 @@ pub fn unregister_file(scheme: SchemeId, number: usize) {
 //
 // }
 
-pub fn trigger(scheme: SchemeId, number: usize, flags: usize) {
+pub fn trigger(scheme: SchemeId, number: usize, flags: EventFlags) {
     let registry = registry();
 
     if let Some(queue_list) = registry.get(&RegKey { scheme, number }) {
-        for (queue_key, queue_flags) in queue_list.iter() {
+        for (queue_key, &queue_flags) in queue_list.iter() {
             let common_flags = flags & queue_flags;
-            if common_flags != 0 {
+            if !common_flags.is_empty() {
                 let queues = queues();
                 if let Some(queue) = queues.get(&queue_key.queue) {
                     queue.queue.send(Event {
diff --git a/src/ptrace.rs b/src/ptrace.rs
index 0bf8bf78..0de6b055 100644
--- a/src/ptrace.rs
+++ b/src/ptrace.rs
@@ -16,7 +16,13 @@ use crate::{
     context::{self, signal, Context, ContextId, Status},
     event,
     scheme::proc,
-    sync::WaitCondition
+    sync::WaitCondition,
+    syscall::{
+        data::PtraceEvent,
+        error::*,
+        flag::*,
+        ptrace_event
+    },
 };
 
 use alloc::{
@@ -34,12 +40,6 @@ use core::{
     sync::atomic::Ordering
 };
 use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
-use syscall::{
-    data::PtraceEvent,
-    error::*,
-    flag::*,
-    ptrace_event
-};
 
 //  ____                _
 // / ___|  ___  ___ ___(_) ___  _ __  ___
@@ -96,10 +96,10 @@ pub fn is_traced(pid: ContextId) -> bool {
 }
 
 /// Used for getting the flags in fevent
-pub fn session_fevent_flags(pid: ContextId) -> Option<usize> {
+pub fn session_fevent_flags(pid: ContextId) -> Option<EventFlags> {
     let sessions = sessions();
     let session = sessions.get(&pid)?;
-    let mut flags = 0;
+    let mut flags = EventFlags::empty();
     if !session.events.is_empty() {
         flags |= EVENT_READ;
     }
@@ -119,7 +119,7 @@ pub fn close_session(pid: ContextId) {
 }
 
 /// Trigger a notification to the event: scheme
-fn proc_trigger_event(file_id: usize, flags: usize) {
+fn proc_trigger_event(file_id: usize, flags: EventFlags) {
     event::trigger(proc::PROC_SCHEME_ID.load(Ordering::SeqCst), file_id, flags);
 }
 
@@ -175,7 +175,7 @@ pub fn recv_events(pid: ContextId, out: &mut [PtraceEvent]) -> Option<usize> {
 #[derive(Debug)]
 struct Breakpoint {
     reached: bool,
-    flags: u64
+    flags: PtraceFlags
 }
 
 /// Continue the process with the specified ID
@@ -195,7 +195,7 @@ pub fn cont(pid: ContextId) {
 
 /// Create a new breakpoint for the specified tracee, optionally with
 /// a sysemu flag. Panics if the session is invalid.
-pub fn set_breakpoint(pid: ContextId, flags: u64) {
+pub fn set_breakpoint(pid: ContextId, flags: PtraceFlags) {
     let mut sessions = sessions_mut();
     let session = sessions.get_mut(&pid).expect("proc (set_breakpoint): invalid session");
     session.breakpoint = Some(Breakpoint {
@@ -246,7 +246,7 @@ pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> {
 
 /// Notify the tracer and await green flag to continue.
 /// Note: Don't call while holding any locks, this will switch contexts
-pub fn breakpoint_callback(match_flags: u64, event: Option<PtraceEvent>) -> Option<u64> {
+pub fn breakpoint_callback(match_flags: PtraceFlags, event: Option<PtraceEvent>) -> Option<PtraceFlags> {
     // Can't hold any locks when executing wait()
     let (tracee, flags) = {
         let contexts = context::contexts();
@@ -289,7 +289,7 @@ pub fn breakpoint_callback(match_flags: u64, event: Option<PtraceEvent>) -> Opti
 /// Obtain the next breakpoint flags for the current process. This is
 /// used for detecting whether or not the tracer decided to use sysemu
 /// mode.
-pub fn next_breakpoint() -> Option<u64> {
+pub fn next_breakpoint() -> Option<PtraceFlags> {
     let contexts = context::contexts();
     let context = contexts.current()?;
     let context = context.read();
diff --git a/src/scheme/debug.rs b/src/scheme/debug.rs
index 4ec00e5a..abcb60c0 100644
--- a/src/scheme/debug.rs
+++ b/src/scheme/debug.rs
@@ -5,7 +5,7 @@ use crate::arch::debug::Writer;
 use crate::event;
 use crate::scheme::*;
 use crate::sync::WaitQueue;
-use crate::syscall::flag::{EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
+use crate::syscall::flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
 use crate::syscall::scheme::Scheme;
 
 pub static DEBUG_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
@@ -102,13 +102,13 @@ impl Scheme for DebugScheme {
         }
     }
 
-    fn fevent(&self, id: usize, _flags: usize) -> Result<usize> {
+    fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
         let _flags = {
             let handles = handles();
             *handles.get(&id).ok_or(Error::new(EBADF))?
         };
 
-        Ok(0)
+        Ok(EventFlags::empty())
     }
 
     fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs
index eb51768b..f7a4e373 100644
--- a/src/scheme/irq.rs
+++ b/src/scheme/irq.rs
@@ -6,7 +6,7 @@ use crate::event;
 use crate::interrupt::irq::acknowledge;
 use crate::scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
 use crate::syscall::error::*;
-use crate::syscall::flag::EVENT_READ;
+use crate::syscall::flag::{EventFlags, EVENT_READ};
 use crate::syscall::scheme::Scheme;
 
 pub static IRQ_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
@@ -87,8 +87,8 @@ impl Scheme for IrqScheme {
         Ok(0)
     }
 
-    fn fevent(&self, _id: usize, _flags: usize) -> Result<usize> {
-        Ok(0)
+    fn fevent(&self, _id: usize, _flags: EventFlags) -> Result<EventFlags> {
+        Ok(EventFlags::empty())
     }
 
     fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
diff --git a/src/scheme/itimer.rs b/src/scheme/itimer.rs
index 3a91c3a2..92ca1ab0 100644
--- a/src/scheme/itimer.rs
+++ b/src/scheme/itimer.rs
@@ -5,7 +5,7 @@ use spin::RwLock;
 
 use crate::syscall::data::ITimerSpec;
 use crate::syscall::error::*;
-use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC};
+use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC, EventFlags};
 use crate::syscall::scheme::Scheme;
 
 pub struct ITimerScheme {
@@ -79,9 +79,9 @@ impl Scheme for ITimerScheme {
         Ok(0)
     }
 
-    fn fevent(&self, id: usize, _flags: usize) ->  Result<usize> {
+    fn fevent(&self, id: usize, _flags: EventFlags) ->  Result<EventFlags> {
         let handles = self.handles.read();
-        handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0))
+        handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(EventFlags::empty()))
     }
 
     fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs
index fd14ab31..b837f56b 100644
--- a/src/scheme/memory.rs
+++ b/src/scheme/memory.rs
@@ -5,7 +5,7 @@ use crate::paging::VirtualAddress;
 use crate::paging::entry::EntryFlags;
 use crate::syscall::data::{Map, StatVfs};
 use crate::syscall::error::*;
-use crate::syscall::flag::{PROT_EXEC, PROT_READ, PROT_WRITE};
+use crate::syscall::flag::{ProtFlags, PROT_EXEC, PROT_READ, PROT_WRITE};
 use crate::syscall::scheme::Scheme;
 
 pub struct MemoryScheme;
@@ -47,13 +47,13 @@ impl Scheme for MemoryScheme {
             let mut to_address = crate::USER_GRANT_OFFSET;
 
             let mut entry_flags = EntryFlags::PRESENT | EntryFlags::USER_ACCESSIBLE;
-            if map.flags & PROT_EXEC == 0 {
+            if map.flags & PROT_EXEC == ProtFlags::empty() {
                 entry_flags |= EntryFlags::NO_EXECUTE;
             }
-            if map.flags & PROT_READ > 0 {
+            if map.flags & PROT_READ != ProtFlags::empty() {
                 //TODO: PROT_READ
             }
-            if map.flags & PROT_WRITE > 0 {
+            if map.flags & PROT_WRITE != ProtFlags::empty() {
                 entry_flags |= EntryFlags::WRITABLE;
             }
 
diff --git a/src/scheme/pipe.rs b/src/scheme/pipe.rs
index 7c02c077..bfc52321 100644
--- a/src/scheme/pipe.rs
+++ b/src/scheme/pipe.rs
@@ -7,7 +7,7 @@ use crate::event;
 use crate::scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
 use crate::sync::WaitCondition;
 use crate::syscall::error::{Error, Result, EAGAIN, EBADF, EINTR, EINVAL, EPIPE, ESPIPE};
-use crate::syscall::flag::{EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_FIFO};
+use crate::syscall::flag::{EventFlags, EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_FIFO};
 use crate::syscall::scheme::Scheme;
 use crate::syscall::data::Stat;
 
@@ -87,14 +87,14 @@ impl Scheme for PipeScheme {
         Err(Error::new(EBADF))
     }
 
-    fn fevent(&self, id: usize, flags: usize) -> Result<usize> {
+    fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
         let pipes = pipes();
 
         if let Some(pipe) = pipes.0.get(&id) {
             if flags == EVENT_READ {
                 // TODO: Return correct flags
                 if pipe.vec.lock().is_empty() {
-                    return Ok(0);
+                    return Ok(EventFlags::empty());
                 } else {
                     return Ok(EVENT_READ);
                 }
diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs
index fe76c3e9..57d06e0f 100644
--- a/src/scheme/proc.rs
+++ b/src/scheme/proc.rs
@@ -418,15 +418,16 @@ impl Scheme for ProcScheme {
                 let len = bytes.len();
                 bytes.copy_from_slice(&buf[0..len]);
                 let op = u64::from_ne_bytes(bytes);
+                let op = PtraceFlags::from_bits(op).ok_or(Error::new(EINVAL))?;
 
-                if op & PTRACE_FLAG_WAIT != PTRACE_FLAG_WAIT || op & PTRACE_STOP_MASK != 0 {
+                if !op.contains(PTRACE_FLAG_WAIT) || op.intersects(PTRACE_STOP_MASK) {
                     ptrace::cont(info.pid);
                 }
-                if op & PTRACE_STOP_MASK != 0 {
+                if op.intersects(PTRACE_STOP_MASK) {
                     ptrace::set_breakpoint(info.pid, op);
                 }
 
-                if op & PTRACE_STOP_SINGLESTEP == PTRACE_STOP_SINGLESTEP {
+                if op.contains(PTRACE_STOP_SINGLESTEP) {
                     // try_stop_context with `false` will
                     // automatically disable ptrace_stop
                     try_stop_context(info.pid, false, |context| {
@@ -452,7 +453,7 @@ impl Scheme for ProcScheme {
                     })?;
                 }
 
-                if op & PTRACE_FLAG_WAIT == PTRACE_FLAG_WAIT || info.flags & O_NONBLOCK != O_NONBLOCK {
+                if op.contains(PTRACE_FLAG_WAIT) || info.flags & O_NONBLOCK != O_NONBLOCK {
                     if let Some(event) = ptrace::wait(info.pid)? {
                         if event.cause == PTRACE_EVENT_CLONE {
                             clones.push(ContextId::from(event.a));
@@ -477,7 +478,7 @@ impl Scheme for ProcScheme {
         }
     }
 
-    fn fevent(&self, id: usize, _flags: usize) -> Result<usize> {
+    fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
         let handles = self.handles.read();
         let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
         let handle = handle.lock();
diff --git a/src/scheme/root.rs b/src/scheme/root.rs
index 13f90891..c4315cd4 100644
--- a/src/scheme/root.rs
+++ b/src/scheme/root.rs
@@ -9,7 +9,7 @@ use spin::{Mutex, RwLock};
 use crate::context;
 use crate::syscall::data::Stat;
 use crate::syscall::error::*;
-use crate::syscall::flag::{O_CREAT, MODE_FILE, MODE_DIR, SEEK_SET, SEEK_CUR, SEEK_END};
+use crate::syscall::flag::{EventFlags, O_CREAT, MODE_FILE, MODE_DIR, SEEK_SET, SEEK_CUR, SEEK_END};
 use crate::syscall::scheme::Scheme;
 use crate::scheme::{self, SchemeNamespace, SchemeId};
 use crate::scheme::user::{UserInner, UserScheme};
@@ -226,7 +226,7 @@ impl Scheme for RootScheme {
         }
     }
 
-    fn fevent(&self, file: usize, flags: usize) -> Result<usize> {
+    fn fevent(&self, file: usize, flags: EventFlags) -> Result<EventFlags> {
         let handle = {
             let handles = self.handles.read();
             let handle = handles.get(&file).ok_or(Error::new(EBADF))?;
diff --git a/src/scheme/time.rs b/src/scheme/time.rs
index 8b340fb4..718d14dc 100644
--- a/src/scheme/time.rs
+++ b/src/scheme/time.rs
@@ -7,7 +7,7 @@ use crate::context::timeout;
 use crate::scheme::SchemeId;
 use crate::syscall::data::TimeSpec;
 use crate::syscall::error::*;
-use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC};
+use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC, EventFlags};
 use crate::syscall::scheme::Scheme;
 use crate::time;
 
@@ -90,9 +90,9 @@ impl Scheme for TimeScheme {
         Ok(0)
     }
 
-    fn fevent(&self, id: usize, _flags: usize) ->  Result<usize> {
+    fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
         let handles = self.handles.read();
-        handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0))
+        handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(EventFlags::empty()))
     }
 
     fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
diff --git a/src/scheme/user.rs b/src/scheme/user.rs
index 11a86200..547c123d 100644
--- a/src/scheme/user.rs
+++ b/src/scheme/user.rs
@@ -16,7 +16,7 @@ use crate::scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
 use crate::sync::{WaitQueue, WaitMap};
 use crate::syscall::data::{Map, Packet, Stat, StatVfs, TimeSpec};
 use crate::syscall::error::*;
-use crate::syscall::flag::{EVENT_READ, O_NONBLOCK, PROT_EXEC, PROT_READ, PROT_WRITE};
+use crate::syscall::flag::{EventFlags, EVENT_READ, O_NONBLOCK, ProtFlags, PROT_EXEC, PROT_READ, PROT_WRITE};
 use crate::syscall::number::*;
 use crate::syscall::scheme::Scheme;
 
@@ -108,7 +108,7 @@ impl UserInner {
         UserInner::capture_inner(&self.context, buf.as_mut_ptr() as usize, buf.len(), PROT_WRITE, None)
     }
 
-    fn capture_inner(context_weak: &Weak<RwLock<Context>>, address: usize, size: usize, flags: usize, desc_opt: Option<FileDescriptor>) -> Result<usize> {
+    fn capture_inner(context_weak: &Weak<RwLock<Context>>, address: usize, size: usize, flags: ProtFlags, desc_opt: Option<FileDescriptor>) -> Result<usize> {
         //TODO: Abstract with other grant creation
         if size == 0 {
             Ok(0)
@@ -127,13 +127,13 @@ impl UserInner {
             let mut to_address = crate::USER_GRANT_OFFSET;
 
             let mut entry_flags = EntryFlags::PRESENT | EntryFlags::USER_ACCESSIBLE;
-            if flags & PROT_EXEC == 0 {
+            if !flags.contains(PROT_EXEC) {
                 entry_flags |= EntryFlags::NO_EXECUTE;
             }
-            if flags & PROT_READ > 0 {
+            if flags.contains(PROT_READ) {
                 //TODO: PROT_READ
             }
-            if flags & PROT_WRITE > 0 {
+            if flags.contains(PROT_WRITE) {
                 entry_flags |= EntryFlags::WRITABLE;
             }
 
@@ -232,7 +232,7 @@ impl UserInner {
             let mut packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) };
             if packet.id == 0 {
                 match packet.a {
-                    SYS_FEVENT => event::trigger(self.scheme_id.load(Ordering::SeqCst), packet.b, packet.c),
+                    SYS_FEVENT => event::trigger(self.scheme_id.load(Ordering::SeqCst), packet.b, EventFlags::from_bits_truncate(packet.c)),
                     _ => println!("Unknown scheme -> kernel message {}", packet.a)
                 }
             } else {
@@ -257,8 +257,8 @@ impl UserInner {
         Ok(i * packet_size)
     }
 
-    pub fn fevent(&self, _flags: usize) -> Result<usize> {
-        Ok(0)
+    pub fn fevent(&self, _flags: EventFlags) -> Result<EventFlags> {
+        Ok(EventFlags::empty())
     }
 
     pub fn fsync(&self) -> Result<usize> {
@@ -356,9 +356,9 @@ impl Scheme for UserScheme {
         inner.call(SYS_FCNTL, file, cmd, arg)
     }
 
-    fn fevent(&self, file: usize, flags: usize) -> Result<usize> {
+    fn fevent(&self, file: usize, flags: EventFlags) -> Result<EventFlags> {
         let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
-        inner.call(SYS_FEVENT, file, flags, 0)
+        inner.call(SYS_FEVENT, file, flags.bits(), 0).map(EventFlags::from_bits_truncate)
     }
 
     fn fmap(&self, file: usize, map: &Map) -> Result<usize> {
diff --git a/src/syscall/driver.rs b/src/syscall/driver.rs
index 1ab0a4cb..e1655fdb 100644
--- a/src/syscall/driver.rs
+++ b/src/syscall/driver.rs
@@ -5,7 +5,7 @@ use crate::paging::entry::EntryFlags;
 use crate::context;
 use crate::context::memory::Grant;
 use crate::syscall::error::{Error, EFAULT, EINVAL, ENOMEM, EPERM, ESRCH, Result};
-use crate::syscall::flag::{PHYSMAP_WRITE, PHYSMAP_WRITE_COMBINE, PHYSMAP_NO_CACHE};
+use crate::syscall::flag::{PhysmapFlags, PHYSMAP_WRITE, PHYSMAP_WRITE_COMBINE, PHYSMAP_NO_CACHE};
 
 fn enforce_root() -> Result<()> {
     let contexts = context::contexts();
@@ -50,7 +50,7 @@ pub fn physfree(physical_address: usize, size: usize) -> Result<usize> {
 }
 
 //TODO: verify exlusive access to physical memory
-pub fn inner_physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
+pub fn inner_physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
     //TODO: Abstract with other grant creation
     if size == 0 {
         Ok(0)
@@ -67,13 +67,13 @@ pub fn inner_physmap(physical_address: usize, size: usize, flags: usize) -> Resu
         let mut to_address = crate::USER_GRANT_OFFSET;
 
         let mut entry_flags = EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE;
-        if flags & PHYSMAP_WRITE == PHYSMAP_WRITE {
+        if flags.contains(PHYSMAP_WRITE) {
             entry_flags |= EntryFlags::WRITABLE;
         }
-        if flags & PHYSMAP_WRITE_COMBINE == PHYSMAP_WRITE_COMBINE {
+        if flags.contains(PHYSMAP_WRITE_COMBINE) {
             entry_flags |= EntryFlags::HUGE_PAGE;
         }
-        if flags & PHYSMAP_NO_CACHE == PHYSMAP_NO_CACHE {
+        if flags.contains(PHYSMAP_NO_CACHE) {
             entry_flags |= EntryFlags::NO_CACHE;
         }
 
@@ -100,7 +100,7 @@ pub fn inner_physmap(physical_address: usize, size: usize, flags: usize) -> Resu
         Ok(to_address + offset)
     }
 }
-pub fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
+pub fn physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
     enforce_root()?;
     inner_physmap(physical_address, size, flags)
 }
diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs
index 1746d77a..c4bcc6c9 100644
--- a/src/syscall/fs.rs
+++ b/src/syscall/fs.rs
@@ -8,7 +8,7 @@ use crate::scheme::{self, FileHandle};
 use crate::syscall;
 use crate::syscall::data::{Packet, Stat};
 use crate::syscall::error::*;
-use crate::syscall::flag::{F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_DUPFD, O_ACCMODE, O_DIRECTORY, O_RDONLY, O_SYMLINK, O_WRONLY, MODE_DIR, MODE_FILE, O_CLOEXEC};
+use crate::syscall::flag::*;
 use crate::context::file::{FileDescriptor, FileDescription};
 
 pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
@@ -92,7 +92,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
         (context.canonicalize(path), context.euid, context.egid, context.ens, context.umask)
     };
 
-    let flags = (flags & (!0o777)) | (flags & 0o777) & (!(umask & 0o777));
+    let flags = (flags & (!0o777)) | ((flags & 0o777) & (!(umask & 0o777)));
 
     //println!("open {}", unsafe { ::core::str::from_utf8_unchecked(&path_canon) });
 
diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs
index 33ac677a..50cacdcb 100644
--- a/src/syscall/mod.rs
+++ b/src/syscall/mod.rs
@@ -16,6 +16,7 @@ pub use self::validate::*;
 
 use self::data::{SigAction, TimeSpec};
 use self::error::{Error, Result, ENOSYS};
+use self::flag::{CloneFlags, PhysmapFlags, ProtFlags, WaitFlags};
 use self::number::*;
 
 use crate::context::ContextId;
@@ -94,8 +95,9 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
                 SYS_GETPGID => getpgid(ContextId::from(b)).map(ContextId::into),
                 SYS_GETPPID => getppid().map(ContextId::into),
                 SYS_CLONE => {
+                    let b = CloneFlags::from_bits_truncate(b);
                     let old_rsp = stack.iret.rsp;
-                    if b & flag::CLONE_STACK == flag::CLONE_STACK {
+                    if b.contains(flag::CLONE_STACK) {
                         stack.iret.rsp = c;
                     }
                     let ret = clone(b, bp).map(ContextId::into);
@@ -104,7 +106,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
                 },
                 SYS_EXIT => exit((b & 0xFF) << 8),
                 SYS_KILL => kill(ContextId::from(b), c),
-                SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into),
+                SYS_WAITPID => waitpid(ContextId::from(b), c, WaitFlags::from_bits_truncate(d)).map(ContextId::into),
                 SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?),
                 SYS_IOPL => iopl(b, stack),
                 SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
@@ -114,7 +116,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
                 SYS_GETGID => getgid(),
                 SYS_GETNS => getns(),
                 SYS_GETUID => getuid(),
-                SYS_MPROTECT => mprotect(b, c, d),
+                SYS_MPROTECT => mprotect(b, c, ProtFlags::from_bits_truncate(d)),
                 SYS_MKNS => mkns(validate_slice(b as *const [usize; 2], c)?),
                 SYS_SETPGID => setpgid(ContextId::from(b), ContextId::from(c)),
                 SYS_SETREUID => setreuid(b as u32, c as u32),
@@ -151,7 +153,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
                 SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c),
                 SYS_PHYSALLOC => physalloc(b),
                 SYS_PHYSFREE => physfree(b, c),
-                SYS_PHYSMAP => physmap(b, c, d),
+                SYS_PHYSMAP => physmap(b, c, PhysmapFlags::from_bits_truncate(d)),
                 SYS_PHYSUNMAP => physunmap(b),
                 SYS_UMASK => umask(b),
                 SYS_VIRTTOPHYS => virttophys(b),
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 9c9aa268..4f80b775 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -23,10 +23,10 @@ use crate::scheme::FileHandle;
 use crate::start::usermode;
 use crate::syscall::data::{PtraceEvent, SigAction, Stat};
 use crate::syscall::error::*;
-use crate::syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, CLONE_STACK,
-                           PROT_EXEC, PROT_READ, PROT_WRITE, PTRACE_EVENT_CLONE,
-                           SIG_DFL, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, SIGCONT, SIGTERM,
-                           WCONTINUED, WNOHANG, WUNTRACED, wifcontinued, wifstopped};
+use crate::syscall::flag::{CloneFlags, CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND,
+                           CLONE_STACK, ProtFlags, PROT_EXEC, PROT_READ, PROT_WRITE, PTRACE_EVENT_CLONE,
+                           SigActionFlags, SIG_DFL, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, SIGCONT, SIGTERM,
+                           WaitFlags, WCONTINUED, WNOHANG, WUNTRACED, wifcontinued, wifstopped};
 use crate::syscall::ptrace_event;
 use crate::syscall::validate::{validate_slice, validate_slice_mut};
 
@@ -67,7 +67,7 @@ pub fn brk(address: usize) -> Result<usize> {
     }
 }
 
-pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
+pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
     let ppid;
     let pid;
     {
@@ -114,7 +114,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
             sigmask = context.sigmask;
             umask = context.umask;
 
-            if flags & CLONE_VM == CLONE_VM {
+            if flags.contains(CLONE_VM) {
                 cpu_id = context.cpu_id;
             }
 
@@ -155,7 +155,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
                 kstack_option = Some(new_stack);
             }
 
-            if flags & CLONE_VM == CLONE_VM {
+            if flags.contains(CLONE_VM) {
                 for memory_shared in context.image.iter() {
                     image.push(memory_shared.clone());
                 }
@@ -206,7 +206,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
             }
 
             if let Some(ref stack_shared) = context.stack {
-                if flags & CLONE_STACK == CLONE_STACK {
+                if flags.contains(CLONE_STACK) {
                     stack_option = Some(stack_shared.clone());
                 } else {
                     stack_shared.with(|stack| {
@@ -261,7 +261,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
                 };
 
 
-                if flags & CLONE_VM == CLONE_VM {
+                if flags.contains(CLONE_VM) {
                     unsafe {
                         new_tls.load();
                     }
@@ -277,7 +277,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
                 tls_option = Some(new_tls);
             }
 
-            if flags & CLONE_VM == CLONE_VM {
+            if flags.contains(CLONE_VM) {
                 grants = Arc::clone(&context.grants);
             } else {
                 let mut grants_vec = Vec::new();
@@ -288,25 +288,25 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
                 grants = Arc::new(Mutex::new(grants_vec));
             }
 
-            if flags & CLONE_VM == CLONE_VM {
+            if flags.contains(CLONE_VM) {
                 name = Arc::clone(&context.name);
             } else {
                 name = Arc::new(Mutex::new(context.name.lock().clone()));
             }
 
-            if flags & CLONE_FS == CLONE_FS {
+            if flags.contains(CLONE_FS) {
                 cwd = Arc::clone(&context.cwd);
             } else {
                 cwd = Arc::new(Mutex::new(context.cwd.lock().clone()));
             }
 
-            if flags & CLONE_FILES == CLONE_FILES {
+            if flags.contains(CLONE_FILES) {
                 files = Arc::clone(&context.files);
             } else {
                 files = Arc::new(Mutex::new(context.files.lock().clone()));
             }
 
-            if flags & CLONE_SIGHAND == CLONE_SIGHAND {
+            if flags.contains(CLONE_SIGHAND) {
                 actions = Arc::clone(&context.actions);
             } else {
                 actions = Arc::new(Mutex::new(context.actions.lock().clone()));
@@ -315,7 +315,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
 
         // If not cloning files, dup to get a new number from scheme
         // This has to be done outside the context lock to prevent deadlocks
-        if flags & CLONE_FILES == 0 {
+        if !flags.contains(CLONE_FILES) {
             for (_fd, file_option) in files.lock().iter_mut().enumerate() {
                 let new_file_option = if let Some(ref file) = *file_option {
                     Some(FileDescriptor {
@@ -331,7 +331,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
         }
 
         // If not cloning virtual memory, use fmap to re-obtain every grant where possible
-        if flags & CLONE_VM == 0 {
+        if !flags.contains(CLONE_VM) {
             let mut i = 0;
             while i < grants.lock().len() {
                 let remove = false;
@@ -350,7 +350,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
 
         // If vfork, block the current process
         // This has to be done after the operations that may require context switches
-        if flags & CLONE_VFORK == CLONE_VFORK {
+        if flags.contains(CLONE_VFORK) {
             let contexts = context::contexts();
             let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
             let mut context = context_lock.write();
@@ -430,7 +430,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
             // TODO: Clone ksig?
 
             // Setup image, heap, and grants
-            if flags & CLONE_VM == CLONE_VM {
+            if flags.contains(CLONE_VM) {
                 // Copy user image mapping, if found
                 if ! image.is_empty() {
                     let frame = active_table.p4()[crate::USER_PML4].pointed_frame().expect("user image not mapped");
@@ -514,7 +514,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
 
             // Setup user stack
             if let Some(stack_shared) = stack_option {
-                if flags & CLONE_STACK == CLONE_STACK {
+                if flags.contains(CLONE_STACK) {
                     let frame = active_table.p4()[crate::USER_STACK_PML4].pointed_frame().expect("user stack not mapped");
                     let flags = active_table.p4()[crate::USER_STACK_PML4].flags();
                     active_table.with(&mut new_table, &mut temporary_page, |mapper| {
@@ -853,7 +853,7 @@ fn fexec_noreturn(
                 SigAction {
                     sa_handler: unsafe { mem::transmute(SIG_DFL) },
                     sa_mask: [0; 2],
-                    sa_flags: 0,
+                    sa_flags: SigActionFlags::empty(),
                 },
                 0
             ); 128]));
@@ -1290,7 +1290,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
     }
 }
 
-pub fn mprotect(address: usize, size: usize, flags: usize) -> Result<usize> {
+pub fn mprotect(address: usize, size: usize, flags: ProtFlags) -> Result<usize> {
     println!("mprotect {:#X}, {}, {:#X}", address, size, flags);
 
     let end_offset = size.checked_sub(1).ok_or(Error::new(EFAULT))?;
@@ -1304,19 +1304,19 @@ pub fn mprotect(address: usize, size: usize, flags: usize) -> Result<usize> {
     let end_page = Page::containing_address(VirtualAddress::new(end_address));
     for page in Page::range_inclusive(start_page, end_page) {
         if let Some(mut page_flags) = active_table.translate_page_flags(page) {
-            if flags & PROT_EXEC > 0 {
+            if flags.contains(PROT_EXEC) {
                 page_flags.remove(EntryFlags::NO_EXECUTE);
             } else {
                 page_flags.insert(EntryFlags::NO_EXECUTE);
             }
 
-            if flags & PROT_WRITE > 0 {
+            if flags.contains(PROT_WRITE) {
                 //TODO: Not allowing gain of write privileges
             } else {
                 page_flags.remove(EntryFlags::WRITABLE);
             }
 
-            if flags & PROT_READ > 0 {
+            if flags.contains(PROT_READ) {
                 //TODO: No flags for readable pages
             } else {
                 //TODO: No flags for readable pages
@@ -1468,7 +1468,7 @@ fn reap(pid: ContextId) -> Result<ContextId> {
     Ok(pid)
 }
 
-pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result<ContextId> {
+pub fn waitpid(pid: ContextId, status_ptr: usize, flags: WaitFlags) -> Result<ContextId> {
     let (ppid, waitpid) = {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
diff --git a/syscall b/syscall
index edf3c008..9a7bd554 160000
--- a/syscall
+++ b/syscall
@@ -1 +1 @@
-Subproject commit edf3c008dc0a68245a255945d9a70b02c71991a5
+Subproject commit 9a7bd554d57f78214b70f9f0fb0b961e20a6dff7
-- 
GitLab