Fix and update C-interface.

master
WangRunji 6 years ago
parent 3f456a2dc6
commit d1112a3768

@ -13,3 +13,5 @@ panic = 'abort' # prevent `_Unwind_Resume` link error
bitflags = "1.0" bitflags = "1.0"
static_assertions = "0.2.5" static_assertions = "0.2.5"
simple-filesystem = { path = ".." } simple-filesystem = { path = ".." }
spin = "0.4"
lazy_static = { version = "1.1", features = ["spin_no_std"] }

@ -1,9 +1,9 @@
ucore: ucore:
rustup override set nightly-2018-04-01 rustup override set nightly
RUST_TARGET_PATH=$(shell pwd) xargo build --target ucore --release cargo xbuild --target ucore.json --release
install-rust: install-rust:
which cargo || ( curl https://sh.rustup.rs -sSf | sh ) which cargo || ( curl https://sh.rustup.rs -sSf | sh )
which xargo || ( rustup component add rust-src && cargo install xargo ) which cargo-xbuild || ( rustup component add rust-src && cargo install cargo-xbuild )
.PHONY: ucore install-rust .PHONY: ucore install-rust

@ -1,2 +0,0 @@
[dependencies]
alloc = {}

@ -3,8 +3,11 @@
//! NOTE: Must link these sections: //! NOTE: Must link these sections:
//! `*.got.*` `*.data.*` `*.rodata.*` //! `*.got.*` `*.data.*` `*.rodata.*`
#![feature(allocator_api, global_allocator, lang_items)] #![feature(allocator_api)]
#![feature(lang_items)]
#![feature(alloc)] #![feature(alloc)]
#![feature(panic_info_message)]
#![feature(compiler_builtins_lib)]
#![no_std] #![no_std]
#[macro_use] #[macro_use]
@ -14,36 +17,48 @@ extern crate simple_filesystem;
extern crate bitflags; extern crate bitflags;
#[macro_use] #[macro_use]
extern crate static_assertions; extern crate static_assertions;
#[macro_use]
extern crate lazy_static;
extern crate spin;
use alloc::{rc::Rc, boxed::Box, BTreeMap}; use alloc::{sync::Arc, boxed::Box, collections::BTreeMap};
use core::cell::RefCell; use core::cell::RefCell;
use core::slice; use core::slice;
use core::ops::Deref; use core::ops::Deref;
use core::cmp::Ordering; use core::cmp::Ordering;
use alloc::heap::{Alloc, AllocErr, Layout}; use core::alloc::{GlobalAlloc, Layout};
use core::mem::{size_of, self}; use core::mem::{size_of, self};
use core::ptr; use core::ptr;
use simple_filesystem as sfs; use simple_filesystem as sfs;
use simple_filesystem as vfs; use simple_filesystem as vfs;
use vfs::FileSystem;
use spin::Mutex;
/// Lang items for bare lib /// Lang items for bare lib
mod lang { mod lang {
use core;
use alloc::fmt; use alloc::fmt;
use core::panic::PanicInfo;
use core::alloc::Layout;
#[lang = "eh_personality"] #[lang = "eh_personality"]
#[no_mangle] #[no_mangle]
extern fn eh_personality() { extern fn eh_personality() {}
#[lang = "oom"]
#[no_mangle]
extern fn oom(_: Layout) -> ! {
panic!("out of memory");
} }
#[lang = "panic_fmt"] #[panic_handler]
#[no_mangle] #[no_mangle]
extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! { extern fn panic_fmt(info: &PanicInfo) -> ! {
use super::ucore::__panic; use super::ucore::__panic;
let mut s = fmt::format(fmt); let location = info.location().unwrap();
s.push('\0'); let message = info.message().unwrap();
let file = format!("{}\0", file); let s = format!("{}\0", message);
unsafe{ __panic(file.as_ptr(), line as i32, s.as_ptr()) }; let file = format!("{}\0", location.file());
unsafe { __panic(file.as_ptr(), location.line() as i32, s.as_ptr()) };
unreachable!() unreachable!()
} }
} }
@ -51,6 +66,7 @@ mod lang {
/// Depends on ucore /// Depends on ucore
mod ucore { mod ucore {
use super::*; use super::*;
extern { extern {
pub fn kmalloc(size: usize) -> *mut u8; pub fn kmalloc(size: usize) -> *mut u8;
pub fn kfree(ptr: *mut u8); pub fn kfree(ptr: *mut u8);
@ -123,7 +139,7 @@ pub extern fn sfs_do_mount(dev: *mut Device, fs_store: &mut *mut Fs) -> ErrorCod
/// Match struct `inode` in ucore `kern/fs/vfs/inode.h` /// Match struct `inode` in ucore `kern/fs/vfs/inode.h`
#[repr(C)] #[repr(C)]
struct INode { struct INode {
inode: vfs::INodePtr, inode: Arc<vfs::INode>,
// ... fields handled extern // ... fields handled extern
} }
@ -132,7 +148,7 @@ struct INode {
/// Match struct `fs` in ucore `kern/fs/vfs/vfs.h` /// Match struct `fs` in ucore `kern/fs/vfs/vfs.h`
#[repr(C)] #[repr(C)]
pub struct Fs { pub struct Fs {
fs: Rc<vfs::FileSystem>, fs: Arc<vfs::FileSystem>,
// ... fields handled extern // ... fields handled extern
} }
@ -321,11 +337,13 @@ impl AsRef<[u8]> for IoBuf {
unsafe { slice::from_raw_parts(self.base, self.resident as usize) } unsafe { slice::from_raw_parts(self.base, self.resident as usize) }
} }
} }
impl AsMut<[u8]> for IoBuf { impl AsMut<[u8]> for IoBuf {
fn as_mut(&mut self) -> &mut [u8] { fn as_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.base, self.resident as usize) } unsafe { slice::from_raw_parts_mut(self.base, self.resident as usize) }
} }
} }
impl IoBuf { impl IoBuf {
fn skip(&mut self, len: usize) { fn skip(&mut self, len: usize) {
assert!(len as u32 <= self.resident); assert!(len as u32 <= self.resident);
@ -344,12 +362,7 @@ impl IoBuf {
} }
impl vfs::BlockedDevice for Device { impl vfs::BlockedDevice for Device {
fn block_size_log2(&self) -> u8 { const BLOCK_SIZE_LOG2: u8 = 12;
if self.blocksize != 4096 {
unimplemented!("block_size != 4096 is not supported yet");
}
12
}
fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool { fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool {
assert!(buf.len() >= 4096); assert!(buf.len() >= 4096);
@ -387,27 +400,27 @@ impl Device {
} }
} }
impl INode { lazy_static! {
fn get_or_create(vfs_inode: vfs::INodePtr, fs: *mut Fs) -> *mut Self { // vfs::INode addr -> c::INode addr
static mut MAPPER: *mut BTreeMap<usize, *mut INode> = ptr::null_mut(); static ref MAPPER: Mutex<BTreeMap<usize, usize>> = Mutex::new(BTreeMap::new());
}
unsafe {if MAPPER.is_null() {
MAPPER = Box::into_raw(Box::new(BTreeMap::<usize, *mut INode>::new()));
} }
let mapper = unsafe{ &mut *MAPPER }; impl INode {
fn get_or_create(vfs_inode: Arc<vfs::INode>, fs: *mut Fs) -> *mut Self {
let mut mapper = MAPPER.lock();
let addr = vfs_inode.as_ptr() as *const () as usize; use core::mem::transmute;
let (addr, _): (usize, usize) = unsafe { transmute(vfs_inode.as_ref()) };
match mapper.get(&addr) { match mapper.get(&addr) {
Some(&ptr) => ptr, Some(&ptr) => ptr as *mut Self,
None => { None => {
let inode = unsafe { ucore::create_inode_for_sfs(&INODE_OPS, fs) }; let inode = unsafe { ucore::create_inode_for_sfs(&INODE_OPS, fs) };
assert!(!inode.is_null()); assert!(!inode.is_null());
// `inode.inode` is uninitialized, so it must be `replace` out and `forget` // `inode.inode` is uninitialized, so it must be `replace` out and `forget`
mem::forget(mem::replace(unsafe { &mut (*inode).inode }, vfs_inode)); mem::forget(mem::replace(unsafe { &mut (*inode).inode }, vfs_inode));
mapper.insert(addr, inode); mapper.insert(addr, inode as usize);
inode inode
}, }
} }
} }
fn drop(&mut self) { fn drop(&mut self) {
@ -419,7 +432,7 @@ impl From<vfs::FileInfo> for Stat {
fn from(info: vfs::FileInfo) -> Self { fn from(info: vfs::FileInfo) -> Self {
Stat { Stat {
mode: Mode::from(info.type_), mode: Mode::from(info.type_),
nlinks: 0, nlinks: info.nlinks as u32,
blocks: info.blocks as u32, blocks: info.blocks as u32,
size: info.size as u32, size: info.size as u32,
} }
@ -428,7 +441,7 @@ impl From<vfs::FileInfo> for Stat {
static INODE_OPS: INodeOps = { static INODE_OPS: INodeOps = {
impl Deref for INode { impl Deref for INode {
type Target = vfs::INodePtr; type Target = Arc<vfs::INode>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.inode &self.inode
@ -445,25 +458,25 @@ static INODE_OPS: INodeOps = {
} }
extern fn read(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { extern fn read(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode {
println!("inode.read"); println!("inode.read");
let len = inode.borrow().read_at(buf.offset as usize, buf.as_mut()).unwrap(); let len = inode.read_at(buf.offset as usize, buf.as_mut()).unwrap();
buf.skip(len); buf.skip(len);
ErrorCode::Ok ErrorCode::Ok
} }
extern fn write(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { extern fn write(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode {
println!("inode.write"); println!("inode.write");
let len = inode.borrow().write_at(buf.offset as usize, buf.as_ref()).unwrap(); let len = inode.write_at(buf.offset as usize, buf.as_ref()).unwrap();
buf.skip(len); buf.skip(len);
ErrorCode::Ok ErrorCode::Ok
} }
extern fn fstat(inode: &mut INode, stat: &mut Stat) -> ErrorCode { extern fn fstat(inode: &mut INode, stat: &mut Stat) -> ErrorCode {
println!("inode.fstst {:?}", inode.borrow()); println!("inode.fstst {:?}", inode);
let info = inode.borrow().info().unwrap(); let info = inode.info().unwrap();
*stat = Stat::from(info); *stat = Stat::from(info);
ErrorCode::Ok ErrorCode::Ok
} }
extern fn fsync(inode: &mut INode) -> ErrorCode { extern fn fsync(inode: &mut INode) -> ErrorCode {
println!("inode.fsync {:?}", inode.borrow()); println!("inode.fsync {:?}", inode);
inode.borrow_mut().sync().unwrap(); inode.sync().unwrap();
ErrorCode::Ok ErrorCode::Ok
} }
extern fn namefile(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { extern fn namefile(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode {
@ -472,14 +485,14 @@ static INODE_OPS: INodeOps = {
extern fn getdirentry(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode { extern fn getdirentry(inode: &mut INode, buf: &mut IoBuf) -> ErrorCode {
const ENTRY_SIZE: usize = 256; const ENTRY_SIZE: usize = 256;
println!("inode.getdirentry {:#x?}", buf); println!("inode.getdirentry {:#x?}", buf);
if inode.borrow().info().unwrap().type_ != vfs::FileType::Dir { if inode.info().unwrap().type_ != vfs::FileType::Dir {
return ErrorCode::NotDir; return ErrorCode::NotDir;
} }
if buf.offset as usize % ENTRY_SIZE != 0 { if buf.offset as usize % ENTRY_SIZE != 0 {
return ErrorCode::Invalid; return ErrorCode::Invalid;
} }
let id = buf.offset as usize / ENTRY_SIZE; let id = buf.offset as usize / ENTRY_SIZE;
let names = inode.borrow().list().unwrap(); let names = inode.list().unwrap();
if id >= names.len() { if id >= names.len() {
return ErrorCode::NoEntry; return ErrorCode::NoEntry;
} }
@ -489,26 +502,26 @@ static INODE_OPS: INodeOps = {
ErrorCode::Ok ErrorCode::Ok
} }
extern fn reclaim(inode: &mut INode) -> ErrorCode { extern fn reclaim(inode: &mut INode) -> ErrorCode {
println!("inode.reclaim: {:?}", inode.borrow()); println!("inode.reclaim: {:?}", inode);
ErrorCode::Ok ErrorCode::Ok
} }
extern fn gettype(inode: &mut INode, type_store: &mut u32) -> ErrorCode { extern fn gettype(inode: &mut INode, type_store: &mut u32) -> ErrorCode {
println!("inode.gettype: {:?}", inode.borrow()); println!("inode.gettype: {:?}", inode);
let info = inode.borrow().info().unwrap(); let info = inode.info().unwrap();
// Inconsistent docs in ucore ! // Inconsistent docs in ucore !
*type_store = Mode::from(info.type_).bits(); *type_store = Mode::from(info.type_).bits();
ErrorCode::Ok ErrorCode::Ok
} }
extern fn tryseek(inode: &mut INode, pos: i32) -> ErrorCode { extern fn tryseek(inode: &mut INode, pos: i32) -> ErrorCode {
println!("inode.tryseek({:?}) at {:?}", pos, inode.borrow()); println!("inode.tryseek({:?}) at {:?}", pos, inode);
let fs = inode.borrow().fs().upgrade().unwrap(); let fs = inode.fs();
if pos < 0 || pos as usize >= fs.info().max_file_size { if pos < 0 || pos as usize >= fs.info().max_file_size {
return ErrorCode::Invalid; return ErrorCode::Invalid;
} }
let pos = pos as usize; let pos = pos as usize;
let info = inode.borrow().info().unwrap(); let info = inode.info().unwrap();
if pos > info.size { if pos > info.size {
inode.borrow_mut().resize(pos); inode.resize(pos);
} }
return ErrorCode::Ok; return ErrorCode::Ok;
} }
@ -520,8 +533,8 @@ static INODE_OPS: INodeOps = {
} }
extern fn lookup(inode: &mut INode, path: *mut u8, inode_store: &mut *mut INode) -> ErrorCode { extern fn lookup(inode: &mut INode, path: *mut u8, inode_store: &mut *mut INode) -> ErrorCode {
let path = unsafe { libc::from_cstr(path) }; let path = unsafe { libc::from_cstr(path) };
println!("inode.lookup({:?}) at {:?}", path, inode.borrow()); println!("inode.lookup({:?}) at {:?}", path, inode);
let target = inode.borrow().lookup(path); let target = inode.lookup(path);
match target { match target {
Ok(target) => { Ok(target) => {
let fs = unsafe { ucore::inode_get_fs(inode) }; let fs = unsafe { ucore::inode_get_fs(inode) };
@ -529,7 +542,7 @@ static INODE_OPS: INodeOps = {
unsafe { ucore::inode_ref_inc(inode) }; unsafe { ucore::inode_ref_inc(inode) };
*inode_store = inode; *inode_store = inode;
ErrorCode::Ok ErrorCode::Ok
}, }
Err(_) => ErrorCode::NoEntry, Err(_) => ErrorCode::NoEntry,
} }
} }
@ -545,7 +558,7 @@ static INODE_OPS: INodeOps = {
static FS_OPS: FsOps = { static FS_OPS: FsOps = {
impl Deref for Fs { impl Deref for Fs {
type Target = Rc<vfs::FileSystem>; type Target = Arc<vfs::FileSystem>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.fs &self.fs
@ -577,16 +590,12 @@ pub struct UcoreAllocator;
#[global_allocator] #[global_allocator]
pub static UCORE_ALLOCATOR: UcoreAllocator = UcoreAllocator; pub static UCORE_ALLOCATOR: UcoreAllocator = UcoreAllocator;
unsafe impl<'a> Alloc for &'a UcoreAllocator { unsafe impl GlobalAlloc for UcoreAllocator {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
// cprintf!("alloc %d\n", layout.size()); // cprintf!("alloc %d\n", layout.size());
const NULL: *mut u8 = 0 as *mut u8; ucore::kmalloc(layout.size())
match ucore::kmalloc(layout.size()) {
NULL => Err(AllocErr::Exhausted { request: layout }),
ptr => Ok(ptr),
}
} }
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
// cprintf!("free %d\n", layout.size()); // cprintf!("free %d\n", layout.size());
ucore::kfree(ptr); ucore::kfree(ptr);
} }

@ -8,8 +8,10 @@
"features": "-mmx,-sse,+soft-float", "features": "-mmx,-sse,+soft-float",
"os": "none", "os": "none",
"arch": "x86", "arch": "x86",
"linker-flavor": "ld", "linker-flavor": "ld.lld",
"pre-link-args": ["-m32"], "pre-link-args": {
"ld.lld": ["-m32"]
},
"eliminate-frame-pointer": false, "eliminate-frame-pointer": false,
"no-compiler-rt": true, "no-compiler-rt": true,
"morestack": false, "morestack": false,

Loading…
Cancel
Save