diff --git a/context/event.rs b/context/event.rs index 19d119d369e459a36dec01be93bc862d5b6faa2d..a42ecef2cb221f6877aa587bb49740c44ec508ef 100644 --- a/context/event.rs +++ b/context/event.rs @@ -27,7 +27,7 @@ pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> { REGISTRY.call_once(init_registry).write() } -pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool { +pub fn register(fd: usize, scheme_id: usize, event_id: usize) -> bool { let (context_id, events) = { let contexts = context::contexts(); let context_lock = contexts.current().expect("event::register: No context"); @@ -36,7 +36,7 @@ pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool { }; let mut registry = registry_mut(); - let entry = registry.entry((scheme_id, id)).or_insert_with(|| { + let entry = registry.entry((scheme_id, event_id)).or_insert_with(|| { BTreeMap::new() }); if entry.contains_key(&(context_id, fd)) { @@ -47,11 +47,11 @@ pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool { } } -pub fn unregister(fd: usize, scheme_id: usize, id: usize) { +pub fn unregister(fd: usize, scheme_id: usize, event_id: usize) { let mut registry = registry_mut(); let mut remove = false; - if let Some(entry) = registry.get_mut(&(scheme_id, id)) { + if let Some(entry) = registry.get_mut(&(scheme_id, event_id)) { entry.remove(&(context::context_id(), fd)); if entry.is_empty() { @@ -60,13 +60,13 @@ pub fn unregister(fd: usize, scheme_id: usize, id: usize) { } if remove { - registry.remove(&(scheme_id, id)); + registry.remove(&(scheme_id, event_id)); } } -pub fn trigger(scheme_id: usize, id: usize, flags: usize, data: usize) { +pub fn trigger(scheme_id: usize, event_id: usize, flags: usize, data: usize) { let registry = registry(); - if let Some(event_lists) = registry.get(&(scheme_id, id)) { + if let Some(event_lists) = registry.get(&(scheme_id, event_id)) { for entry in event_lists.iter() { if let Some(event_list) = entry.1.upgrade() { event_list.send(Event { diff --git a/context/file.rs b/context/file.rs index 67a28eb86cfd7ccf9cf92b08c4c928ea1d36e79f..d9238d696df8849fb299d1d763f977811d8a47d1 100644 --- a/context/file.rs +++ b/context/file.rs @@ -8,4 +8,6 @@ pub struct File { pub scheme: usize, /// The number the scheme uses to refer to this file pub number: usize, + /// If events are on, this is the event ID + pub event: Option<usize>, } diff --git a/scheme/irq.rs b/scheme/irq.rs index 2ed891e0f60e2b6bc057cfc8997c494dbb372ed5..ce99c42335bcded79be69874b9e602385b5f3680 100644 --- a/scheme/irq.rs +++ b/scheme/irq.rs @@ -93,8 +93,8 @@ impl Scheme for IrqScheme { } } - fn fevent(&self, _file: usize, _flags: usize) -> Result<usize> { - Ok(0) + fn fevent(&self, file: usize, _flags: usize) -> Result<usize> { + Ok(file) } fn fsync(&self, _file: usize) -> Result<usize> { diff --git a/scheme/root.rs b/scheme/root.rs index 1d4d4d0495c783b2b1508de9a73e1545638964f1..57877bf8f6768256addf89cd184a6c41086b8044 100644 --- a/scheme/root.rs +++ b/scheme/root.rs @@ -89,8 +89,8 @@ impl Scheme for RootScheme { inner.write(buf) } - fn fevent(&self, _file: usize, _flags: usize) -> Result<usize> { - Ok(0) + fn fevent(&self, file: usize, _flags: usize) -> Result<usize> { + Ok(file) } fn fsync(&self, _file: usize) -> Result<usize> { diff --git a/syscall/fs.rs b/syscall/fs.rs index fb06884e19a5e4713698886f63be7bd790f76273..6c953e468f2caf6a272a4409c03a0122f9aaea87 100644 --- a/syscall/fs.rs +++ b/syscall/fs.rs @@ -98,7 +98,8 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> { let context = context_lock.read(); context.add_file(::context::file::File { scheme: scheme_id, - number: file_id + number: file_id, + event: None, }).ok_or(Error::new(EMFILE)) } @@ -113,12 +114,14 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> { let read_fd = context.add_file(::context::file::File { scheme: scheme_id, - number: read_id + number: read_id, + event: None, }).ok_or(Error::new(EMFILE))?; let write_fd = context.add_file(::context::file::File { scheme: scheme_id, - number: write_id + number: write_id, + event: None, }).ok_or(Error::new(EMFILE))?; fds[0] = read_fd; @@ -206,7 +209,9 @@ pub fn close(fd: usize) -> Result<usize> { file }; - context::event::unregister(fd, file.scheme, file.number); + if let Some(event_id) = file.event { + context::event::unregister(fd, file.scheme, event_id); + } let scheme = { let schemes = scheme::schemes(); @@ -240,7 +245,8 @@ pub fn dup(fd: usize) -> Result<usize> { let context = context_lock.read(); context.add_file(::context::file::File { scheme: file.scheme, - number: new_id + number: new_id, + event: None, }).ok_or(Error::new(EMFILE)) } @@ -250,8 +256,13 @@ pub fn fevent(fd: usize, flags: usize) -> Result<usize> { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - let file = context.get_file(fd).ok_or(Error::new(EBADF))?; - file + let mut files = context.files.lock(); + let mut file = files.get_mut(fd).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; + if let Some(event_id) = file.event.take() { + println!("{}: {}:{}: events already registered: {}", fd, file.scheme, file.number, event_id); + context::event::unregister(fd, file.scheme, event_id); + } + file.clone() }; let scheme = { @@ -259,7 +270,15 @@ pub fn fevent(fd: usize, flags: usize) -> Result<usize> { let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; scheme.clone() }; - scheme.fevent(file.number, flags)?; - context::event::register(fd, file.scheme, file.number); + let event_id = scheme.fevent(file.number, flags)?; + { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + let mut files = context.files.lock(); + let mut file = files.get_mut(fd).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; + file.event = Some(event_id); + } + context::event::register(fd, file.scheme, event_id); Ok(0) } diff --git a/syscall/process.rs b/syscall/process.rs index 5763c891568c1f9828d0e7e5928663af902b0b9e..ddd2cec9865eeab68e5d0dad9aad728ef8844046 100644 --- a/syscall/process.rs +++ b/syscall/process.rs @@ -232,7 +232,11 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> { }; match result { Ok(new_number) => { - Some(context::file::File { scheme: file.scheme, number: new_number }) + Some(context::file::File { + scheme: file.scheme, + number: new_number, + event: None, + }) }, Err(err) => { println!("clone: failed to dup {}: {:?}", fd, err); @@ -616,7 +620,9 @@ pub fn exit(status: usize) -> ! { /// Files must be closed while context is valid so that messages can be passed for (fd, file_option) in close_files.drain(..).enumerate() { if let Some(file) = file_option { - context::event::unregister(fd, file.scheme, file.number); + if let Some(event_id) = file.event { + context::event::unregister(fd, file.scheme, event_id); + } let scheme_option = { let schemes = scheme::schemes();