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);
@ -105,13 +121,13 @@ mod libc {
#[no_mangle] #[no_mangle]
pub extern fn sfs_do_mount(dev: *mut Device, fs_store: &mut *mut Fs) -> ErrorCode { pub extern fn sfs_do_mount(dev: *mut Device, fs_store: &mut *mut Fs) -> ErrorCode {
use sfs; use sfs;
let fs = unsafe{ ucore::create_fs_for_sfs(&FS_OPS) }; let fs = unsafe { ucore::create_fs_for_sfs(&FS_OPS) };
debug_assert!(!dev.is_null()); debug_assert!(!dev.is_null());
let mut device = unsafe{ Box::from_raw(dev) }; // TODO: fix unsafe let mut device = unsafe { Box::from_raw(dev) }; // TODO: fix unsafe
device.open(); device.open();
let sfs = sfs::SimpleFileSystem::open(device).unwrap(); let sfs = sfs::SimpleFileSystem::open(device).unwrap();
// `fs.fs` is uninitialized, so it must be `replace` out and `forget` // `fs.fs` is uninitialized, so it must be `replace` out and `forget`
mem::forget(mem::replace(unsafe{ &mut (*fs).fs }, sfs)); mem::forget(mem::replace(unsafe { &mut (*fs).fs }, sfs));
*fs_store = fs; *fs_store = fs;
ErrorCode::Ok ErrorCode::Ok
} }
@ -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
} }
@ -263,37 +279,37 @@ pub struct INodeOps {
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum ErrorCode { pub enum ErrorCode {
/// No error /// No error
Ok = 0 , Ok = 0,
/// Unspecified or unknown problem /// Unspecified or unknown problem
UNSPECIFIED = -1 , UNSPECIFIED = -1,
/// Process doesn't exist or otherwise /// Process doesn't exist or otherwise
BAD_PROC = -2 , BAD_PROC = -2,
/// Invalid parameter /// Invalid parameter
Invalid = -3 , Invalid = -3,
/// Request failed due to memory shortage /// Request failed due to memory shortage
NO_MEM = -4 , NO_MEM = -4,
/// Attempt to create a new process beyond /// Attempt to create a new process beyond
NO_FREE_PROC= -5 , NO_FREE_PROC = -5,
/// Memory fault /// Memory fault
FAULT = -6 , FAULT = -6,
/// SWAP READ/WRITE fault /// SWAP READ/WRITE fault
SWAP_FAULT = -7 , SWAP_FAULT = -7,
/// Invalid elf file /// Invalid elf file
INVAL_ELF = -8 , INVAL_ELF = -8,
/// Process is killed /// Process is killed
KILLED = -9 , KILLED = -9,
/// Panic Failure /// Panic Failure
PANIC = -10, PANIC = -10,
/// Timeout /// Timeout
TIMEOUT = -11, TIMEOUT = -11,
/// Argument is Too Big /// Argument is Too Big
TOO_BIG = -12, TOO_BIG = -12,
/// No such Device /// No such Device
NO_DEV = -13, NO_DEV = -13,
/// Device Not Available /// Device Not Available
NA_DEV = -14, NA_DEV = -14,
/// Device/File is Busy /// Device/File is Busy
BUSY = -15, BUSY = -15,
/// No Such File or Directory /// No Such File or Directory
NoEntry = -16, NoEntry = -16,
/// Is a Directory /// Is a Directory
@ -301,35 +317,37 @@ pub enum ErrorCode {
/// Not a Directory /// Not a Directory
NotDir = -18, NotDir = -18,
/// Cross Device-Link /// Cross Device-Link
XDEV = -19, XDEV = -19,
/// Unimplemented Feature /// Unimplemented Feature
Unimplemented = -20, Unimplemented = -20,
/// Illegal Seek /// Illegal Seek
SEEK = -21, SEEK = -21,
/// Too Many Files are Open /// Too Many Files are Open
MAX_OPEN = -22, MAX_OPEN = -22,
/// File/Directory Already Exists /// File/Directory Already Exists
EXISTS = -23, EXISTS = -23,
/// Directory is Not Empty /// Directory is Not Empty
NOTEMPTY = -24, NOTEMPTY = -24,
} }
// Wrapper functions // Wrapper functions
impl AsRef<[u8]> for IoBuf { impl AsRef<[u8]> for IoBuf {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
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);
self.base = unsafe{ self.base.offset(len as isize) }; self.base = unsafe { self.base.offset(len as isize) };
self.offset += len as i32; self.offset += len as i32;
self.resident -= len as u32; self.resident -= len as u32;
} }
@ -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,31 +400,31 @@ 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) {
unsafe{ ucore::inode_kill(self) }; unsafe { ucore::inode_kill(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;
} }
@ -519,17 +532,17 @@ static INODE_OPS: INodeOps = {
unimplemented!(); unimplemented!();
} }
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) };
let inode = INode::get_or_create(target, fs); let inode = INode::get_or_create(target, fs);
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