Add externfn macro and correctly label fixed_stack_segments

This commit is contained in:
Niko Matsakis 2013-08-14 21:41:40 -04:00
parent 303f650ecf
commit 0479d946c8
82 changed files with 890 additions and 86 deletions

View File

@ -19,6 +19,7 @@ extern {
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
}
#[fixed_stack_segment]
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
@ -35,6 +36,11 @@ interfaces that aren't thread-safe, and almost any function that takes a pointer
valid for all possible inputs since the pointer could be dangling, and raw pointers fall outside of
Rust's safe memory model.
Finally, the `#[fixed_stack_segment]` annotation that appears on
`main()` instructs the Rust compiler that when `main()` executes, it
should request a "very large" stack segment. More details on
stack management can be found in the following sections.
When declaring the argument types to a foreign function, the Rust compiler will not check if the
declaration is correct, so specifying it correctly is part of keeping the binding correct at
runtime.
@ -75,6 +81,8 @@ length is number of elements currently contained, and the capacity is the total
the allocated memory. The length is less than or equal to the capacity.
~~~~ {.xfail-test}
#[fixed_stack_segment]
#[inline(never)]
pub fn validate_compressed_buffer(src: &[u8]) -> bool {
unsafe {
snappy_validate_compressed_buffer(vec::raw::to_ptr(src), src.len() as size_t) == 0
@ -86,6 +94,36 @@ The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, b
guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
signature.
The `validate_compressed_buffer` wrapper is also annotated with two
attributes `#[fixed_stack_segment]` and `#[inline(never)]`. The
purpose of these attributes is to guarantee that there will be
sufficient stack for the C function to execute. This is necessary
because Rust, unlike C, does not assume that the stack is allocated in
one continuous chunk. Instead, we rely on a *segmented stack* scheme,
in which the stack grows and shrinks as necessary. C code, however,
expects one large stack, and so callers of C functions must request a
large stack segment to ensure that the C routine will not run off the
end of the stack.
The compiler includes a lint mode that will report an error if you
call a C function without a `#[fixed_stack_segment]` attribute. More
details on the lint mode are given in a later section.
You may be wondering why we include a `#[inline(never)]` directive.
This directive informs the compiler never to inline this function.
While not strictly necessary, it is usually a good idea to use an
`#[inline(never)]` directive in concert with `#[fixed_stack_segment]`.
The reason is that if a fn annotated with `fixed_stack_segment` is
inlined, then its caller also inherits the `fixed_stack_segment`
annotation. This means that rather than requesting a large stack
segment only for the duration of the call into C, the large stack
segment would be used for the entire duration of the caller. This is
not necessarily *bad* -- it can for example be more efficient,
particularly if `validate_compressed_buffer()` is called multiple
times in a row -- but it does work against the purpose of the
segmented stack scheme, which is to keep stacks small and thus
conserve address space.
The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
allocated to hold the output too.
@ -96,6 +134,8 @@ the true length after compression for setting the length.
~~~~ {.xfail-test}
pub fn compress(src: &[u8]) -> ~[u8] {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let srclen = src.len() as size_t;
let psrc = vec::raw::to_ptr(src);
@ -116,6 +156,8 @@ format and `snappy_uncompressed_length` will retrieve the exact buffer size requ
~~~~ {.xfail-test}
pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let srclen = src.len() as size_t;
let psrc = vec::raw::to_ptr(src);
@ -139,6 +181,99 @@ pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
For reference, the examples used here are also available as an [library on
GitHub](https://github.com/thestinger/rust-snappy).
# Automatic wrappers
Sometimes writing Rust wrappers can be quite tedious. For example, if
function does not take any pointer arguments, often there is no need
for translating types. In such cases, it is usually still a good idea
to have a Rust wrapper so as to manage the segmented stacks, but you
can take advantage of the (standard) `externfn!` macro to remove some
of the tedium.
In the initial section, we showed an extern block that added a call
to a specific snappy API:
~~~~ {.xfail-test}
use std::libc::size_t;
#[link_args = "-lsnappy"]
extern {
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
}
#[fixed_stack_segment]
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
}
~~~~
To avoid the need to create a wrapper fn for `snappy_max_compressed_length()`,
and also to avoid the need to think about `#[fixed_stack_segment]`, we
could simply use the `externfn!` macro instead, as shown here:
~~~~ {.xfail-test}
use std::libc::size_t;
externfn!(#[link_args = "-lsnappy"]
fn snappy_max_compressed_length(source_length: size_t) -> size_t)
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
}
~~~~
As you can see from the example, `externfn!` replaces the extern block
entirely. After macro expansion, it will create something like this:
~~~~ {.xfail-test}
use std::libc::size_t;
// Automatically generated by
// externfn!(#[link_args = "-lsnappy"]
// fn snappy_max_compressed_length(source_length: size_t) -> size_t)
unsafe fn snappy_max_compressed_length(source_length: size_t) -> size_t {
#[fixed_stack_segment]; #[inline(never)];
return snappy_max_compressed_length(source_length);
#[link_args = "-lsnappy"]
extern {
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
}
}
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
println(fmt!("max compressed length of a 100 byte buffer: %?", x));
}
~~~~
# Segmented stacks and the linter
By default, whenever you invoke a non-Rust fn, the `cstack` lint will
check that one of the following conditions holds:
1. The call occurs inside of a fn that has been annotated with
`#[fixed_stack_segment]`;
2. The call occurs inside of an `extern fn`;
3. The call occurs within a stack closure created by some other
safe fn.
All of these conditions ensure that you are running on a large stack
segmented. However, they are sometimes too strict. If your application
will be making many calls into C, it is often beneficial to promote
the `#[fixed_stack_segment]` attribute higher up the call chain. For
example, the Rust compiler actually labels main itself as requiring a
`#[fixed_stack_segment]`. In such cases, the linter is just an
annoyance, because all C calls that occur from within the Rust
compiler are made on a large stack. Another situation where this
frequently occurs is on a 64-bit architecture, where large stacks are
the default. In cases, you can disable the linter by including a
`#[allow(cstack)]` directive somewhere, which permits violations of
the "cstack" rules given above (you can also use `#[warn(cstack)]` to
convert the errors into warnings, if you prefer).
# Destructors
Foreign libraries often hand off ownership of resources to the calling code,
@ -161,6 +296,9 @@ pub struct Unique<T> {
impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> {
#[fixed_stack_segment];
#[inline(never)];
unsafe {
let ptr = malloc(std::sys::size_of::<T>() as size_t) as *mut T;
assert!(!ptr::is_null(ptr));
@ -184,6 +322,9 @@ impl<T: Send> Unique<T> {
#[unsafe_destructor]
impl<T: Send> Drop for Unique<T> {
fn drop(&self) {
#[fixed_stack_segment];
#[inline(never)];
unsafe {
let x = intrinsics::init(); // dummy value to swap in
// moving the object out is needed to call the destructor

View File

@ -155,12 +155,20 @@ mod tests {
use std::libc;
fn malloc(n: size_t) -> CVec<u8> {
#[fixed_stack_segment];
#[inline(never)];
unsafe {
let mem = libc::malloc(n);
assert!(mem as int != 0);
c_vec_with_dtor(mem as *mut u8, n as uint, || free(mem))
return c_vec_with_dtor(mem as *mut u8, n as uint, || f(mem));
}
fn f(mem: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
unsafe { libc::free(mem) }
}
}

View File

@ -47,6 +47,8 @@ static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adle
static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] {
#[fixed_stack_segment]; #[inline(never)];
do bytes.as_imm_buf |b, len| {
unsafe {
let mut outsz : size_t = 0;
@ -73,6 +75,8 @@ pub fn deflate_bytes_zlib(bytes: &[u8]) -> ~[u8] {
}
fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] {
#[fixed_stack_segment]; #[inline(never)];
do bytes.as_imm_buf |b, len| {
unsafe {
let mut outsz : size_t = 0;

View File

@ -19,15 +19,25 @@ use std::str;
pub mod rustrt {
use std::libc::{c_char, c_int};
extern {
pub fn linenoise(prompt: *c_char) -> *c_char;
pub fn linenoiseHistoryAdd(line: *c_char) -> c_int;
pub fn linenoiseHistorySetMaxLen(len: c_int) -> c_int;
pub fn linenoiseHistorySave(file: *c_char) -> c_int;
pub fn linenoiseHistoryLoad(file: *c_char) -> c_int;
pub fn linenoiseSetCompletionCallback(callback: *u8);
pub fn linenoiseAddCompletion(completions: *(), line: *c_char);
#[cfg(stage0)]
mod macro_hack {
#[macro_escape];
macro_rules! externfn(
(fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
extern {
fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
}
)
)
}
externfn!(fn linenoise(prompt: *c_char) -> *c_char)
externfn!(fn linenoiseHistoryAdd(line: *c_char) -> c_int)
externfn!(fn linenoiseHistorySetMaxLen(len: c_int) -> c_int)
externfn!(fn linenoiseHistorySave(file: *c_char) -> c_int)
externfn!(fn linenoiseHistoryLoad(file: *c_char) -> c_int)
externfn!(fn linenoiseSetCompletionCallback(callback: *u8))
externfn!(fn linenoiseAddCompletion(completions: *(), line: *c_char))
}
/// Add a line to history
@ -84,7 +94,7 @@ pub unsafe fn complete(cb: CompletionCb) {
rustrt::linenoiseAddCompletion(completions, buf);
}
}
}
}
}
}

View File

@ -188,6 +188,8 @@ fn optgroups() -> ~[getopts::groups::OptGroup] {
}
fn usage(binary: &str, helpstr: &str) -> ! {
#[fixed_stack_segment]; #[inline(never)];
let message = fmt!("Usage: %s [OPTIONS] [FILTER]", binary);
println(groups::usage(message, optgroups()));
println("");

View File

@ -64,6 +64,8 @@ impl Ord for Timespec {
* nanoseconds since 1970-01-01T00:00:00Z.
*/
pub fn get_time() -> Timespec {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut sec = 0i64;
let mut nsec = 0i32;
@ -78,6 +80,8 @@ pub fn get_time() -> Timespec {
* in nanoseconds since an unspecified epoch.
*/
pub fn precise_time_ns() -> u64 {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut ns = 0u64;
rustrt::precise_time_ns(&mut ns);
@ -95,6 +99,8 @@ pub fn precise_time_s() -> float {
}
pub fn tzset() {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
rustrt::rust_tzset();
}
@ -135,6 +141,8 @@ pub fn empty_tm() -> Tm {
/// Returns the specified time in UTC
pub fn at_utc(clock: Timespec) -> Tm {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let Timespec { sec, nsec } = clock;
let mut tm = empty_tm();
@ -150,6 +158,8 @@ pub fn now_utc() -> Tm {
/// Returns the specified time in the local timezone
pub fn at(clock: Timespec) -> Tm {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let Timespec { sec, nsec } = clock;
let mut tm = empty_tm();
@ -176,6 +186,8 @@ pub fn strftime(format: &str, tm: &Tm) -> ~str {
impl Tm {
/// Convert time to the seconds from January 1, 1970
pub fn to_timespec(&self) -> Timespec {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let sec = match self.tm_gmtoff {
0_i32 => rustrt::rust_timegm(self),

View File

@ -229,6 +229,8 @@ fn usage() {
}
pub fn main() {
#[fixed_stack_segment]; #[inline(never)];
let os_args = os::args();
if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {

View File

@ -645,9 +645,13 @@ pub fn build_session_options(binary: @str,
}
debugging_opts |= this_bit;
}
if debugging_opts & session::debug_llvm != 0 {
unsafe {
llvm::LLVMSetDebug(1);
set_llvm_debug();
fn set_llvm_debug() {
#[fixed_stack_segment]; #[inline(never)];
unsafe { llvm::LLVMSetDebug(1); }
}
}

View File

@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// LLVM wrappers are intended to be called from trans,
// which already runs in a #[fixed_stack_segment]
#[allow(cstack)];
use std::c_str::ToCStr;
use std::hashmap::HashMap;
use std::libc::{c_uint, c_ushort};

View File

@ -19,6 +19,7 @@ large stacks.
use middle::lint;
use middle::ty;
use syntax::ast;
use syntax::ast_map;
use syntax::attr;
use syntax::codemap::span;
use visit = syntax::oldvisit;
@ -47,19 +48,33 @@ pub fn stack_check_crate(tcx: ty::ctxt,
fn stack_check_item(item: @ast::item,
(in_cx, v): (Context, visit::vt<Context>)) {
let safe_stack = match item.node {
match item.node {
ast::item_fn(_, ast::extern_fn, _, _, _) => {
// an extern fn is already being called from C code...
let new_cx = Context {safe_stack: true, ..in_cx};
visit::visit_item(item, (new_cx, v));
}
ast::item_fn(*) => {
attr::contains_name(item.attrs, "fixed_stack_segment")
let safe_stack = fixed_stack_segment(item.attrs);
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
visit::visit_item(item, (new_cx, v));
}
ast::item_impl(_, _, _, ref methods) => {
// visit_method() would make this nicer
for &method in methods.iter() {
let safe_stack = fixed_stack_segment(method.attrs);
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
visit::visit_method_helper(method, (new_cx, v));
}
}
_ => {
false
visit::visit_item(item, (in_cx, v));
}
};
let new_cx = Context {
tcx: in_cx.tcx,
safe_stack: safe_stack
};
visit::visit_item(item, (new_cx, v));
}
fn fixed_stack_segment(attrs: &[ast::Attribute]) -> bool {
attr::contains_name(attrs, "fixed_stack_segment")
}
}
fn stack_check_fn<'a>(fk: &visit::fn_kind,
@ -69,13 +84,23 @@ fn stack_check_fn<'a>(fk: &visit::fn_kind,
id: ast::NodeId,
(in_cx, v): (Context, visit::vt<Context>)) {
let safe_stack = match *fk {
visit::fk_item_fn(*) => in_cx.safe_stack, // see stack_check_item above
visit::fk_anon(*) | visit::fk_fn_block | visit::fk_method(*) => false,
};
let new_cx = Context {
tcx: in_cx.tcx,
safe_stack: safe_stack
visit::fk_method(*) | visit::fk_item_fn(*) => {
in_cx.safe_stack // see stack_check_item above
}
visit::fk_anon(*) | visit::fk_fn_block => {
match ty::get(ty::node_id_to_type(in_cx.tcx, id)).sty {
ty::ty_bare_fn(*) |
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) |
ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
false
}
_ => {
in_cx.safe_stack
}
}
}
};
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
debug!("stack_check_fn(safe_stack=%b, id=%?)", safe_stack, id);
visit::visit_fn(fk, decl, body, sp, id, (new_cx, v));
}
@ -92,12 +117,7 @@ fn stack_check_expr<'a>(expr: @ast::expr,
match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref fty) => {
if !fty.abis.is_rust() && !fty.abis.is_intrinsic() {
cx.tcx.sess.add_lint(
lint::cstack,
callee.id,
callee.span,
fmt!("invoking non-Rust fn in fn without \
#[fixed_stack_segment]"));
call_to_extern_fn(cx, callee);
}
}
_ => {}
@ -108,3 +128,32 @@ fn stack_check_expr<'a>(expr: @ast::expr,
}
visit::visit_expr(expr, (cx, v));
}
fn call_to_extern_fn(cx: Context, callee: @ast::expr) {
// Permit direct calls to extern fns that are annotated with
// #[rust_stack]. This is naturally a horrible pain to achieve.
match callee.node {
ast::expr_path(*) => {
match cx.tcx.def_map.find(&callee.id) {
Some(&ast::def_fn(id, _)) if id.crate == ast::LOCAL_CRATE => {
match cx.tcx.items.find(&id.node) {
Some(&ast_map::node_foreign_item(item, _, _, _)) => {
if attr::contains_name(item.attrs, "rust_stack") {
return;
}
}
_ => {}
}
}
_ => {}
}
}
_ => {}
}
cx.tcx.sess.add_lint(lint::cstack,
callee.id,
callee.span,
fmt!("invoking non-Rust fn in fn without \
#[fixed_stack_segment]"));
}

View File

@ -2509,14 +2509,14 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
register_method(ccx, id, pth, m)
}
ast_map::node_foreign_item(ni, _, _, pth) => {
ast_map::node_foreign_item(ni, abis, _, pth) => {
let ty = ty::node_id_to_type(ccx.tcx, ni.id);
exprt = true;
match ni.node {
ast::foreign_item_fn(*) => {
let path = vec::append((*pth).clone(), [path_name(ni.ident)]);
foreign::register_foreign_item_fn(ccx, abis, &path, ni);
foreign::register_foreign_item_fn(ccx, abis, &path, ni)
}
ast::foreign_item_static(*) => {
let ident = token::ident_to_str(&ni.ident);

View File

@ -17,6 +17,11 @@
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
// Rustc tasks always run on a fixed_stack_segment, so code in this
// module can call C functions (in particular, LLVM functions) with
// impunity.
#[allow(cstack)];
extern mod extra;
extern mod syntax;

View File

@ -498,6 +498,8 @@ pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~st
}
pub fn main() {
#[fixed_stack_segment]; #[inline(never)];
let args = os::args();
let input = io::stdin();
let out = io::stdout();

View File

@ -382,6 +382,8 @@ pub fn find_and_install_dependencies(ctxt: &Ctx,
#[cfg(windows)]
pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
/* FIXME (#1768): Investigate how to do this on win32
Node wraps symlinks by having a .bat,
but that won't work with minGW. */
@ -394,6 +396,8 @@ pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
pub fn link_exe(src: &Path, dest: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
use std::c_str::ToCStr;
use std::libc;

View File

@ -96,6 +96,7 @@ impl CString {
///
/// Fails if the CString is null.
pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
#[fixed_stack_segment]; #[inline(never)];
if self.buf.is_null() { fail!("CString is null!"); }
unsafe {
let len = libc::strlen(self.buf) as uint;
@ -114,6 +115,7 @@ impl CString {
impl Drop for CString {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
if self.owns_buffer_ {
unsafe {
libc::free(self.buf as *libc::c_void)
@ -172,6 +174,7 @@ impl<'self> ToCStr for &'self str {
impl<'self> ToCStr for &'self [u8] {
fn to_c_str(&self) -> CString {
#[fixed_stack_segment]; #[inline(never)];
let mut cs = unsafe { self.to_c_str_unchecked() };
do cs.with_mut_ref |buf| {
for i in range(0, self.len()) {
@ -190,6 +193,7 @@ impl<'self> ToCStr for &'self [u8] {
}
unsafe fn to_c_str_unchecked(&self) -> CString {
#[fixed_stack_segment]; #[inline(never)];
do self.as_imm_buf |self_buf, self_len| {
let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
if buf.is_null() {
@ -260,12 +264,16 @@ mod tests {
#[test]
fn test_unwrap() {
#[fixed_stack_segment]; #[inline(never)];
let c_str = "hello".to_c_str();
unsafe { libc::free(c_str.unwrap() as *libc::c_void) }
}
#[test]
fn test_with_ref() {
#[fixed_stack_segment]; #[inline(never)];
let c_str = "hello".to_c_str();
let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
assert!(!c_str.is_null());

View File

@ -928,6 +928,8 @@ fn convert_whence(whence: SeekStyle) -> i32 {
impl Reader for *libc::FILE {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do bytes.as_mut_buf |buf_p, buf_len| {
assert!(buf_len >= len);
@ -950,16 +952,22 @@ impl Reader for *libc::FILE {
}
}
fn read_byte(&self) -> int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::fgetc(*self) as int
}
}
fn eof(&self) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
return libc::feof(*self) != 0 as c_int;
}
}
fn seek(&self, offset: int, whence: SeekStyle) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
assert!(libc::fseek(*self,
offset as c_long,
@ -967,6 +975,8 @@ impl Reader for *libc::FILE {
}
}
fn tell(&self) -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
return libc::ftell(*self) as uint;
}
@ -1005,6 +1015,8 @@ impl FILERes {
impl Drop for FILERes {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::fclose(self.f);
}
@ -1035,12 +1047,16 @@ pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
* ~~~
*/
pub fn stdin() -> @Reader {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
@rustrt::rust_get_stdin() as @Reader
}
}
pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
#[fixed_stack_segment]; #[inline(never)];
let f = do path.with_c_str |pathbuf| {
do "rb".with_c_str |modebuf| {
unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
@ -1162,6 +1178,8 @@ impl<W:Writer,C> Writer for Wrapper<W, C> {
impl Writer for *libc::FILE {
fn write(&self, v: &[u8]) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do v.as_imm_buf |vbuf, len| {
let nout = libc::fwrite(vbuf as *c_void,
@ -1177,6 +1195,8 @@ impl Writer for *libc::FILE {
}
}
fn seek(&self, offset: int, whence: SeekStyle) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
assert!(libc::fseek(*self,
offset as c_long,
@ -1184,16 +1204,22 @@ impl Writer for *libc::FILE {
}
}
fn tell(&self) -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::ftell(*self) as uint
}
}
fn flush(&self) -> int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::fflush(*self) as int
}
}
fn get_type(&self) -> WriterType {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let fd = libc::fileno(*self);
if libc::isatty(fd) == 0 { File }
@ -1212,6 +1238,8 @@ pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
impl Writer for fd_t {
fn write(&self, v: &[u8]) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut count = 0u;
do v.as_imm_buf |vbuf, len| {
@ -1238,6 +1266,8 @@ impl Writer for fd_t {
}
fn flush(&self) -> int { 0 }
fn get_type(&self) -> WriterType {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
if libc::isatty(*self) == 0 { File } else { Screen }
}
@ -1256,6 +1286,8 @@ impl FdRes {
impl Drop for FdRes {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::close(self.fd);
}
@ -1273,6 +1305,8 @@ pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
-> Result<@Writer, ~str> {
#[fixed_stack_segment]; #[inline(never)];
#[cfg(windows)]
fn wb() -> c_int {
(O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
@ -1573,6 +1607,8 @@ pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
// FIXME: fileflags // #2004
pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let f = do path.with_c_str |pathbuf| {
do "w".with_c_str |modebuf| {
@ -1803,12 +1839,13 @@ pub mod fsync {
blk: &fn(v: Res<*libc::FILE>)) {
blk(Res::new(Arg {
val: file.f, opt_level: opt_level,
fsync_fn: |file, l| {
unsafe {
os::fsync_fd(libc::fileno(*file), l) as int
}
}
fsync_fn: |file, l| fsync_fd(fileno(*file), l)
}));
fn fileno(stream: *libc::FILE) -> libc::c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe { libc::fileno(stream) }
}
}
// fsync fd after executing blk
@ -1816,10 +1853,16 @@ pub mod fsync {
blk: &fn(v: Res<fd_t>)) {
blk(Res::new(Arg {
val: fd.fd, opt_level: opt_level,
fsync_fn: |fd, l| os::fsync_fd(*fd, l) as int
fsync_fn: |fd, l| fsync_fd(*fd, l)
}));
}
fn fsync_fd(fd: libc::c_int, level: Level) -> int {
#[fixed_stack_segment]; #[inline(never)];
os::fsync_fd(fd, level) as int
}
// Type of objects that may want to fsync
pub trait FSyncable { fn fsync(&self, l: Level) -> int; }

View File

@ -2762,9 +2762,11 @@ pub mod funcs {
// doesn't link it correctly on i686, so we're going
// through a C function that mysteriously does work.
pub unsafe fn opendir(dirname: *c_char) -> *DIR {
#[fixed_stack_segment]; #[inline(never)];
rust_opendir(dirname)
}
pub unsafe fn readdir(dirp: *DIR) -> *dirent_t {
#[fixed_stack_segment]; #[inline(never)];
rust_readdir(dirp)
}

View File

@ -41,7 +41,7 @@ macro_rules! delegate(
use unstable::intrinsics;
$(
#[inline]
#[inline] #[fixed_stack_segment] #[inline(never)]
pub fn $name($( $arg : $arg_ty ),*) -> $rv {
unsafe {
$bound_name($( $arg ),*)

View File

@ -43,7 +43,7 @@ macro_rules! delegate(
use unstable::intrinsics;
$(
#[inline]
#[inline] #[fixed_stack_segment] #[inline(never)]
pub fn $name($( $arg : $arg_ty ),*) -> $rv {
unsafe {
$bound_name($( $arg ),*)

View File

@ -51,6 +51,7 @@ pub use os::consts::*;
/// Delegates to the libc close() function, returning the same return value.
pub fn close(fd: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::close(fd)
}
@ -70,6 +71,7 @@ pub static TMPBUF_SZ : uint = 1000u;
static BUF_BYTES : uint = 2048u;
pub fn getcwd() -> Path {
#[fixed_stack_segment]; #[inline(never)];
let mut buf = [0 as libc::c_char, ..BUF_BYTES];
do buf.as_mut_buf |buf, len| {
unsafe {
@ -109,6 +111,8 @@ pub mod win32 {
pub fn fill_utf16_buf_and_decode(f: &fn(*mut u16, DWORD) -> DWORD)
-> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut n = TMPBUF_SZ as DWORD;
let mut res = None;
@ -145,6 +149,18 @@ pub mod win32 {
}
}
#[cfg(stage0)]
mod macro_hack {
#[macro_escape];
macro_rules! externfn(
(fn $name:ident ()) => (
extern {
fn $name();
}
)
)
}
/*
Accessing environment variables is not generally threadsafe.
Serialize access through a global lock.
@ -161,12 +177,8 @@ fn with_env_lock<T>(f: &fn() -> T) -> T {
};
}
extern {
#[fast_ffi]
fn rust_take_env_lock();
#[fast_ffi]
fn rust_drop_env_lock();
}
externfn!(fn rust_take_env_lock());
externfn!(fn rust_drop_env_lock());
}
/// Returns a vector of (variable, value) pairs for all the environment
@ -175,6 +187,8 @@ pub fn env() -> ~[(~str,~str)] {
unsafe {
#[cfg(windows)]
unsafe fn get_env_pairs() -> ~[~str] {
#[fixed_stack_segment]; #[inline(never)];
use libc::funcs::extra::kernel32::{
GetEnvironmentStringsA,
FreeEnvironmentStringsA
@ -198,6 +212,8 @@ pub fn env() -> ~[(~str,~str)] {
}
#[cfg(unix)]
unsafe fn get_env_pairs() -> ~[~str] {
#[fixed_stack_segment]; #[inline(never)];
extern {
fn rust_env_pairs() -> **libc::c_char;
}
@ -237,6 +253,7 @@ pub fn env() -> ~[(~str,~str)] {
/// Fetches the environment variable `n` from the current process, returning
/// None if the variable isn't set.
pub fn getenv(n: &str) -> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do with_env_lock {
let s = do n.with_c_str |buf| {
@ -255,6 +272,8 @@ pub fn getenv(n: &str) -> Option<~str> {
/// Fetches the environment variable `n` from the current process, returning
/// None if the variable isn't set.
pub fn getenv(n: &str) -> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do with_env_lock {
use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
@ -272,6 +291,7 @@ pub fn getenv(n: &str) -> Option<~str> {
/// Sets the environment variable `n` to the value `v` for the currently running
/// process
pub fn setenv(n: &str, v: &str) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do with_env_lock {
do n.with_c_str |nbuf| {
@ -288,6 +308,8 @@ pub fn setenv(n: &str, v: &str) {
/// Sets the environment variable `n` to the value `v` for the currently running
/// process
pub fn setenv(n: &str, v: &str) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do with_env_lock {
use os::win32::as_utf16_p;
@ -304,6 +326,7 @@ pub fn setenv(n: &str, v: &str) {
pub fn unsetenv(n: &str) {
#[cfg(unix)]
fn _unsetenv(n: &str) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do with_env_lock {
do n.with_c_str |nbuf| {
@ -314,6 +337,7 @@ pub fn unsetenv(n: &str) {
}
#[cfg(windows)]
fn _unsetenv(n: &str) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do with_env_lock {
use os::win32::as_utf16_p;
@ -328,6 +352,7 @@ pub fn unsetenv(n: &str) {
}
pub fn fdopen(fd: c_int) -> *FILE {
#[fixed_stack_segment]; #[inline(never)];
do "r".with_c_str |modebuf| {
unsafe {
libc::fdopen(fd, modebuf)
@ -340,6 +365,7 @@ pub fn fdopen(fd: c_int) -> *FILE {
#[cfg(windows)]
pub fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::extra::msvcrt::*;
return commit(fd);
@ -349,6 +375,7 @@ pub fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::posix01::unistd::*;
match level {
@ -361,6 +388,8 @@ pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
#[cfg(target_os = "macos")]
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::consts::os::extra::*;
use libc::funcs::posix88::fcntl::*;
@ -381,6 +410,8 @@ pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
#[cfg(target_os = "freebsd")]
pub fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::posix01::unistd::*;
return fsync(fd);
@ -394,6 +425,7 @@ pub struct Pipe {
#[cfg(unix)]
pub fn pipe() -> Pipe {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut fds = Pipe {input: 0 as c_int,
out: 0 as c_int };
@ -406,6 +438,7 @@ pub fn pipe() -> Pipe {
#[cfg(windows)]
pub fn pipe() -> Pipe {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
// Windows pipes work subtly differently than unix pipes, and their
// inheritance has to be handled in a different way that I do not
@ -424,6 +457,7 @@ pub fn pipe() -> Pipe {
}
fn dup2(src: c_int, dst: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::dup2(src, dst)
}
@ -440,6 +474,7 @@ pub fn self_exe_path() -> Option<Path> {
#[cfg(target_os = "freebsd")]
fn load_self() -> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::bsd44::*;
use libc::consts::os::extra::*;
@ -458,6 +493,7 @@ pub fn self_exe_path() -> Option<Path> {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn load_self() -> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::posix01::unistd::readlink;
@ -479,6 +515,7 @@ pub fn self_exe_path() -> Option<Path> {
#[cfg(target_os = "macos")]
fn load_self() -> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do fill_charp_buf() |buf, sz| {
let mut sz = sz as u32;
@ -490,6 +527,7 @@ pub fn self_exe_path() -> Option<Path> {
#[cfg(windows)]
fn load_self() -> Option<~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::fill_utf16_buf_and_decode;
do fill_utf16_buf_and_decode() |buf, sz| {
@ -592,6 +630,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
/// Indicates whether a path represents a directory
pub fn path_is_dir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do p.with_c_str |buf| {
rustrt::rust_path_is_dir(buf) != 0 as c_int
@ -601,6 +640,7 @@ pub fn path_is_dir(p: &Path) -> bool {
/// Indicates whether a path exists
pub fn path_exists(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do p.with_c_str |buf| {
rustrt::rust_path_exists(buf) != 0 as c_int
@ -633,6 +673,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
#[cfg(windows)]
fn mkdir(p: &Path, _mode: c_int) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
// FIXME: turn mode into something useful? #2623
@ -645,6 +686,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
#[cfg(unix)]
fn mkdir(p: &Path, mode: c_int) -> bool {
#[fixed_stack_segment]; #[inline(never)];
do p.with_c_str |buf| {
unsafe {
libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int)
@ -689,6 +731,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
unsafe fn get_list(p: &Path) -> ~[~str] {
#[fixed_stack_segment]; #[inline(never)];
use libc::{dirent_t};
use libc::{opendir, readdir, closedir};
extern {
@ -721,6 +764,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
}
#[cfg(windows)]
unsafe fn get_list(p: &Path) -> ~[~str] {
#[fixed_stack_segment]; #[inline(never)];
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
use libc::{wcslen, free};
use libc::funcs::extra::kernel32::{
@ -809,6 +853,7 @@ pub fn remove_dir(p: &Path) -> bool {
#[cfg(windows)]
fn rmdir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(p.to_str()) |buf| {
@ -819,6 +864,7 @@ pub fn remove_dir(p: &Path) -> bool {
#[cfg(unix)]
fn rmdir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
do p.with_c_str |buf| {
unsafe {
libc::rmdir(buf) == (0 as c_int)
@ -834,6 +880,7 @@ pub fn change_dir(p: &Path) -> bool {
#[cfg(windows)]
fn chdir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(p.to_str()) |buf| {
@ -844,6 +891,7 @@ pub fn change_dir(p: &Path) -> bool {
#[cfg(unix)]
fn chdir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
do p.with_c_str |buf| {
unsafe {
libc::chdir(buf) == (0 as c_int)
@ -858,6 +906,7 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
#[cfg(windows)]
fn do_copy_file(from: &Path, to: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(from.to_str()) |fromp| {
@ -871,6 +920,7 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
#[cfg(unix)]
fn do_copy_file(from: &Path, to: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let istream = do from.with_c_str |fromp| {
do "rb".with_c_str |modebuf| {
@ -933,6 +983,7 @@ pub fn remove_file(p: &Path) -> bool {
#[cfg(windows)]
fn unlink(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(p.to_str()) |buf| {
@ -943,6 +994,7 @@ pub fn remove_file(p: &Path) -> bool {
#[cfg(unix)]
fn unlink(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do p.with_c_str |buf| {
libc::unlink(buf) == (0 as c_int)
@ -957,6 +1009,7 @@ pub fn errno() -> int {
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn errno_location() -> *c_int {
#[fixed_stack_segment]; #[inline(never)];
#[nolink]
extern {
fn __error() -> *c_int;
@ -969,6 +1022,7 @@ pub fn errno() -> int {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn errno_location() -> *c_int {
#[fixed_stack_segment]; #[inline(never)];
#[nolink]
extern {
fn __errno_location() -> *c_int;
@ -986,6 +1040,7 @@ pub fn errno() -> int {
#[cfg(windows)]
/// Returns the platform-specific value of errno
pub fn errno() -> uint {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::DWORD;
#[link_name = "kernel32"]
@ -1008,6 +1063,8 @@ pub fn last_os_error() -> ~str {
#[cfg(target_os = "freebsd")]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t)
-> c_int {
#[fixed_stack_segment]; #[inline(never)];
#[nolink]
extern {
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t)
@ -1023,6 +1080,7 @@ pub fn last_os_error() -> ~str {
// So we just use __xpg_strerror_r which is always POSIX compliant
#[cfg(target_os = "linux")]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
#[nolink]
extern {
fn __xpg_strerror_r(errnum: c_int,
@ -1050,6 +1108,8 @@ pub fn last_os_error() -> ~str {
#[cfg(windows)]
fn strerror() -> ~str {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::DWORD;
use libc::types::os::arch::extra::LPSTR;
use libc::types::os::arch::extra::LPVOID;
@ -1129,6 +1189,8 @@ unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
*/
#[cfg(target_os = "macos")]
pub fn real_args() -> ~[~str] {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let (argc, argv) = (*_NSGetArgc() as c_int,
*_NSGetArgv() as **c_char);
@ -1150,6 +1212,8 @@ pub fn real_args() -> ~[~str] {
#[cfg(windows)]
pub fn real_args() -> ~[~str] {
#[fixed_stack_segment]; #[inline(never)];
let mut nArgs: c_int = 0;
let lpArgCount: *mut c_int = &mut nArgs;
let lpCmdLine = unsafe { GetCommandLineW() };
@ -1232,6 +1296,8 @@ pub fn set_args(new_args: ~[~str]) {
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
pub fn glob(pattern: &str) -> ~[Path] {
#[fixed_stack_segment]; #[inline(never)];
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn default_glob_t () -> libc::glob_t {
@ -1326,6 +1392,8 @@ fn round_up(from: uint, to: uint) -> uint {
#[cfg(unix)]
pub fn page_size() -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::sysconf(libc::_SC_PAGESIZE) as uint
}
@ -1333,6 +1401,8 @@ pub fn page_size() -> uint {
#[cfg(windows)]
pub fn page_size() -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut info = libc::SYSTEM_INFO::new();
libc::GetSystemInfo(&mut info);
@ -1404,6 +1474,8 @@ impl to_str::ToStr for MapError {
#[cfg(unix)]
impl MemoryMap {
pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError> {
#[fixed_stack_segment]; #[inline(never)];
use libc::off_t;
let mut addr: *c_void = ptr::null();
@ -1460,6 +1532,8 @@ impl MemoryMap {
#[cfg(unix)]
impl Drop for MemoryMap {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
match libc::munmap(self.data as *c_void, self.len) {
0 => (),
@ -1476,6 +1550,8 @@ impl Drop for MemoryMap {
#[cfg(windows)]
impl MemoryMap {
pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError> {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::{LPVOID, DWORD, SIZE_T, HANDLE};
let mut lpAddress: LPVOID = ptr::mut_null();
@ -1569,6 +1645,8 @@ impl MemoryMap {
#[cfg(windows)]
impl Drop for MemoryMap {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::{LPCVOID, HANDLE};
unsafe {
@ -1921,6 +1999,8 @@ mod tests {
#[test]
fn copy_file_ok() {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let tempdir = getcwd(); // would like to use $TMPDIR,
// doesn't seem to work on Linux
@ -1991,17 +2071,23 @@ mod tests {
#[test]
fn memory_map_file() {
#[fixed_stack_segment]; #[inline(never)];
use result::{Ok, Err};
use os::*;
use libc::*;
#[cfg(unix)]
#[fixed_stack_segment]
#[inline(never)]
fn lseek_(fd: c_int, size: uint) {
unsafe {
assert!(lseek(fd, size as off_t, SEEK_SET) == size as off_t);
}
}
#[cfg(windows)]
#[fixed_stack_segment]
#[inline(never)]
fn lseek_(fd: c_int, size: uint) {
unsafe {
assert!(lseek(fd, size as c_long, SEEK_SET) == size as c_long);

View File

@ -381,6 +381,7 @@ mod stat {
#[cfg(target_os = "win32")]
impl WindowsPath {
pub fn stat(&self) -> Option<libc::stat> {
#[fixed_stack_segment]; #[inline(never)];
do self.with_c_str |buf| {
let mut st = stat::arch::default_stat();
match unsafe { libc::stat(buf, &mut st) } {
@ -415,6 +416,7 @@ impl WindowsPath {
#[cfg(not(target_os = "win32"))]
impl PosixPath {
pub fn stat(&self) -> Option<libc::stat> {
#[fixed_stack_segment]; #[inline(never)];
do self.with_c_str |buf| {
let mut st = stat::arch::default_stat();
match unsafe { libc::stat(buf as *libc::c_char, &mut st) } {
@ -493,6 +495,7 @@ impl PosixPath {
#[cfg(unix)]
impl PosixPath {
pub fn lstat(&self) -> Option<libc::stat> {
#[fixed_stack_segment]; #[inline(never)];
do self.with_c_str |buf| {
let mut st = stat::arch::default_stat();
match unsafe { libc::lstat(buf, &mut st) } {
@ -1101,6 +1104,8 @@ pub mod windows {
}
pub fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
if (s.len() > 1 &&
libc::isalpha(s[0] as libc::c_int) != 0 &&

View File

@ -877,6 +877,8 @@ impl Rng for XorShiftRng {
impl XorShiftRng {
/// Create an xor shift random number generator with a random seed.
pub fn new() -> XorShiftRng {
#[fixed_stack_segment]; #[inline(never)];
// generate seeds the same way as seed(), except we have a spceific size
let mut s = [0u8, ..16];
loop {
@ -910,6 +912,8 @@ impl XorShiftRng {
/// Create a new random seed.
pub fn seed() -> ~[u8] {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let n = rustrt::rand_seed_size() as uint;
let mut s = vec::from_elem(n, 0_u8);
@ -1142,6 +1146,8 @@ mod test {
#[test]
fn compare_isaac_implementation() {
#[fixed_stack_segment]; #[inline(never)];
// This is to verify that the implementation of the ISAAC rng is
// correct (i.e. matches the output of the upstream implementation,
// which is in the runtime)

View File

@ -118,12 +118,22 @@ mod imp {
args
}
extern {
fn rust_take_global_args_lock();
fn rust_drop_global_args_lock();
fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>;
#[cfg(stage0)]
mod macro_hack {
#[macro_escape];
macro_rules! externfn(
(fn $name:ident () $(-> $ret_ty:ty),*) => (
extern {
fn $name() $(-> $ret_ty),*;
}
)
)
}
externfn!(fn rust_take_global_args_lock())
externfn!(fn rust_drop_global_args_lock())
externfn!(fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>)
#[cfg(test)]
mod tests {
use option::{Some, None};

View File

@ -136,6 +136,7 @@ impl DebugPrints for io::fd_t {
}
unsafe fn write_cstr(&self, p: *c_char) {
#[fixed_stack_segment]; #[inline(never)];
use libc::strlen;
use vec;

View File

@ -35,8 +35,9 @@ fn align_to(size: uint, align: uint) -> uint {
}
/// A wrapper around libc::malloc, aborting on out-of-memory
#[inline]
pub unsafe fn malloc_raw(size: uint) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
let p = malloc(size as size_t);
if p.is_null() {
// we need a non-allocating way to print an error here
@ -46,8 +47,9 @@ pub unsafe fn malloc_raw(size: uint) -> *c_void {
}
/// A wrapper around libc::realloc, aborting on out-of-memory
#[inline]
pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
#[fixed_stack_segment]; #[inline(never)];
let p = realloc(ptr, size as size_t);
if p.is_null() {
// we need a non-allocating way to print an error here
@ -97,8 +99,9 @@ pub unsafe fn exchange_free_(ptr: *c_char) {
exchange_free(ptr)
}
#[inline]
pub unsafe fn exchange_free(ptr: *c_char) {
#[fixed_stack_segment]; #[inline(never)];
free(ptr as *c_void);
}

View File

@ -37,6 +37,7 @@ pub struct LocalHeap {
}
impl LocalHeap {
#[fixed_stack_segment] #[inline(never)]
pub fn new() -> LocalHeap {
unsafe {
// Don't need synchronization for the single-threaded local heap
@ -55,18 +56,21 @@ impl LocalHeap {
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox {
unsafe {
return rust_boxed_region_malloc(self.boxed_region, td, size as size_t);
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn realloc(&mut self, ptr: *OpaqueBox, size: uint) -> *OpaqueBox {
unsafe {
return rust_boxed_region_realloc(self.boxed_region, ptr, size as size_t);
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn free(&mut self, box: *OpaqueBox) {
unsafe {
return rust_boxed_region_free(self.boxed_region, box);
@ -75,6 +79,7 @@ impl LocalHeap {
}
impl Drop for LocalHeap {
#[fixed_stack_segment] #[inline(never)]
fn drop(&self) {
unsafe {
rust_delete_boxed_region(self.boxed_region);

View File

@ -24,6 +24,8 @@ use unstable::finally::Finally;
use tls = rt::thread_local_storage;
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
#[fixed_stack_segment]
#[inline(never)]
pub fn init_tls_key() {
unsafe {
rust_initialize_rt_tls_key();
@ -124,6 +126,8 @@ fn tls_key() -> tls::Key {
}
}
#[fixed_stack_segment]
#[inline(never)]
fn maybe_tls_key() -> Option<tls::Key> {
unsafe {
let key: *mut c_void = rust_get_rt_tls_key();
@ -149,8 +153,6 @@ fn maybe_tls_key() -> Option<tls::Key> {
}
extern {
#[fast_ffi]
fn rust_get_rt_tls_key() -> *mut c_void;
}
}

View File

@ -57,6 +57,7 @@ impl Logger for StdErrLogger {
/// Configure logging by traversing the crate map and setting the
/// per-module global logging flags based on the logging spec
#[fixed_stack_segment] #[inline(never)]
pub fn init(crate_map: *u8) {
use c_str::ToCStr;
use os;
@ -78,8 +79,13 @@ pub fn init(crate_map: *u8) {
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn console_on() { unsafe { rust_log_console_on() } }
#[fixed_stack_segment] #[inline(never)]
pub fn console_off() { unsafe { rust_log_console_off() } }
#[fixed_stack_segment] #[inline(never)]
fn should_log_console() -> bool { unsafe { rust_should_log_console() != 0 } }
extern {

View File

@ -200,6 +200,18 @@ pub fn start_on_main_thread(argc: int, argv: **u8, crate_map: *u8, main: ~fn())
return exit_code;
}
#[cfg(stage0)]
mod macro_hack {
#[macro_escape];
macro_rules! externfn(
(fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
extern {
fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
}
)
)
}
/// One-time runtime initialization.
///
/// Initializes global state, including frobbing
@ -215,9 +227,7 @@ pub fn init(argc: int, argv: **u8, crate_map: *u8) {
rust_update_gc_metadata(crate_map);
}
extern {
fn rust_update_gc_metadata(crate_map: *u8);
}
externfn!(fn rust_update_gc_metadata(crate_map: *u8));
}
/// One-time runtime cleanup.

View File

@ -21,6 +21,8 @@ pub struct StackSegment {
impl StackSegment {
pub fn new(size: uint) -> StackSegment {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
// Crate a block of uninitialized values
let mut stack = vec::with_capacity(size);
@ -50,6 +52,8 @@ impl StackSegment {
impl Drop for StackSegment {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
// XXX: Using the FFI to call a C macro. Slow
rust_valgrind_stack_deregister(self.valgrind_id);

View File

@ -441,6 +441,8 @@ impl Unwinder {
}
pub fn begin_unwind(&mut self) -> ! {
#[fixed_stack_segment]; #[inline(never)];
self.unwinding = true;
unsafe {
rust_begin_unwind(UNWIND_TOKEN);

View File

@ -98,6 +98,8 @@ mod darwin_fd_limit {
static RLIMIT_NOFILE: libc::c_int = 8;
pub unsafe fn raise_fd_limit() {
#[fixed_stack_segment]; #[inline(never)];
// The strategy here is to fetch the current resource limits, read the kern.maxfilesperproc
// sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
use ptr::{to_unsafe_ptr, to_mut_unsafe_ptr, mut_null};
@ -305,6 +307,7 @@ pub fn cleanup_task(mut task: ~Task) {
}
/// Get a port number, starting at 9600, for use in tests
#[fixed_stack_segment] #[inline(never)]
pub fn next_test_port() -> u16 {
unsafe {
return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;

View File

@ -23,6 +23,8 @@ pub struct Thread {
impl Thread {
pub fn start(main: ~fn()) -> Thread {
fn substart(main: &~fn()) -> *raw_thread {
#[fixed_stack_segment]; #[inline(never)];
unsafe { rust_raw_thread_start(main) }
}
let raw = substart(&main);
@ -34,6 +36,8 @@ impl Thread {
}
pub fn join(self) {
#[fixed_stack_segment]; #[inline(never)];
assert!(!self.joined);
let mut this = self;
unsafe { rust_raw_thread_join(this.raw_thread); }
@ -43,6 +47,8 @@ impl Thread {
impl Drop for Thread {
fn drop(&self) {
#[fixed_stack_segment]; #[inline(never)];
assert!(self.joined);
unsafe { rust_raw_thread_delete(self.raw_thread) }
}

View File

@ -20,16 +20,22 @@ use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
pub type Key = pthread_key_t;
#[cfg(unix)]
#[fixed_stack_segment]
#[inline(never)]
pub unsafe fn create(key: &mut Key) {
assert_eq!(0, pthread_key_create(key, null()));
}
#[cfg(unix)]
#[fixed_stack_segment]
#[inline(never)]
pub unsafe fn set(key: Key, value: *mut c_void) {
assert_eq!(0, pthread_setspecific(key, value));
}
#[cfg(unix)]
#[fixed_stack_segment]
#[inline(never)]
pub unsafe fn get(key: Key) -> *mut c_void {
pthread_getspecific(key)
}
@ -58,6 +64,8 @@ extern {
pub type Key = DWORD;
#[cfg(windows)]
#[fixed_stack_segment]
#[inline(never)]
pub unsafe fn create(key: &mut Key) {
static TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
*key = TlsAlloc();
@ -65,11 +73,15 @@ pub unsafe fn create(key: &mut Key) {
}
#[cfg(windows)]
#[fixed_stack_segment]
#[inline(never)]
pub unsafe fn set(key: Key, value: *mut c_void) {
assert!(0 != TlsSetValue(key, value))
}
#[cfg(windows)]
#[fixed_stack_segment]
#[inline(never)]
pub unsafe fn get(key: Key) -> *mut c_void {
TlsGetValue(key)
}

View File

@ -17,6 +17,8 @@ use str::StrSlice;
/// Get the number of cores available
pub fn num_cpus() -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
return rust_get_num_cpus();
}
@ -94,11 +96,16 @@ memory and partly incapable of presentation to others.",
rterrln!("%s", "");
rterrln!("fatal runtime error: %s", msg);
unsafe { libc::abort(); }
abort();
fn abort() -> ! {
#[fixed_stack_segment]; #[inline(never)];
unsafe { libc::abort() }
}
}
pub fn set_exit_status(code: int) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
return rust_set_exit_status_newrt(code as libc::uintptr_t);
}
@ -109,7 +116,7 @@ pub fn set_exit_status(code: int) {
}
pub fn get_exit_status() -> int {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
return rust_get_exit_status_newrt() as int;
}

View File

@ -310,6 +310,8 @@ pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
/// Transmute an owned vector to a Buf
pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let data = malloc(v.len() as size_t) as *u8;
assert!(data.is_not_null());
@ -323,6 +325,8 @@ pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
/// Transmute a Buf that was once a ~[u8] back to ~[u8]
pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> {
#[fixed_stack_segment]; #[inline(never)];
if !(buf.len == 0 && buf.base.is_null()) {
let v = unsafe { vec::from_buf(buf.base, buf.len as uint) };
unsafe { free(buf.base as *c_void) };

View File

@ -45,6 +45,7 @@ enum SocketNameKind {
fn socket_name<T, U: Watcher + NativeHandle<*T>>(sk: SocketNameKind,
handle: U) -> Result<SocketAddr, IoError> {
#[fixed_stack_segment]; #[inline(never)];
let getsockname = match sk {
TcpPeer => uvll::rust_uv_tcp_getpeername,
@ -406,6 +407,8 @@ impl RtioTcpListener for UvTcpListener {
}
fn accept_simultaneously(&mut self) -> Result<(), IoError> {
#[fixed_stack_segment]; #[inline(never)];
let r = unsafe {
uvll::rust_uv_tcp_simultaneous_accepts(self.watcher.native_handle(), 1 as c_int)
};
@ -417,6 +420,8 @@ impl RtioTcpListener for UvTcpListener {
}
fn dont_accept_simultaneously(&mut self) -> Result<(), IoError> {
#[fixed_stack_segment]; #[inline(never)];
let r = unsafe {
uvll::rust_uv_tcp_simultaneous_accepts(self.watcher.native_handle(), 0 as c_int)
};
@ -524,6 +529,8 @@ impl RtioTcpStream for UvTcpStream {
}
fn control_congestion(&mut self) -> Result<(), IoError> {
#[fixed_stack_segment]; #[inline(never)];
let r = unsafe {
uvll::rust_uv_tcp_nodelay(self.native_handle(), 0 as c_int)
};
@ -535,6 +542,8 @@ impl RtioTcpStream for UvTcpStream {
}
fn nodelay(&mut self) -> Result<(), IoError> {
#[fixed_stack_segment]; #[inline(never)];
let r = unsafe {
uvll::rust_uv_tcp_nodelay(self.native_handle(), 1 as c_int)
};
@ -546,6 +555,8 @@ impl RtioTcpStream for UvTcpStream {
}
fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError> {
#[fixed_stack_segment]; #[inline(never)];
let r = unsafe {
uvll::rust_uv_tcp_keepalive(self.native_handle(), 1 as c_int,
delay_in_seconds as c_uint)
@ -558,6 +569,8 @@ impl RtioTcpStream for UvTcpStream {
}
fn letdie(&mut self) -> Result<(), IoError> {
#[fixed_stack_segment]; #[inline(never)];
let r = unsafe {
uvll::rust_uv_tcp_keepalive(self.native_handle(), 0 as c_int, 0 as c_uint)
};

View File

@ -124,6 +124,8 @@ pub enum uv_membership {
}
pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
assert!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX);
let size = rust_uv_handle_size(handle as uint);
let p = malloc(size);
@ -132,10 +134,14 @@ pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void {
}
pub unsafe fn free_handle(v: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
free(v)
}
pub unsafe fn malloc_req(req: uv_req_type) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
assert!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX);
let size = rust_uv_req_size(req as uint);
let p = malloc(size);
@ -144,17 +150,22 @@ pub unsafe fn malloc_req(req: uv_req_type) -> *c_void {
}
pub unsafe fn free_req(v: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
free(v)
}
#[test]
fn handle_sanity_check() {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
assert_eq!(UV_HANDLE_TYPE_MAX as uint, rust_uv_handle_type_max());
}
}
#[test]
#[fixed_stack_segment]
#[inline(never)]
fn request_sanity_check() {
unsafe {
assert_eq!(UV_REQ_TYPE_MAX as uint, rust_uv_req_type_max());
@ -162,59 +173,87 @@ fn request_sanity_check() {
}
pub unsafe fn loop_new() -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_loop_new();
}
pub unsafe fn loop_delete(loop_handle: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_loop_delete(loop_handle);
}
pub unsafe fn run(loop_handle: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_run(loop_handle);
}
pub unsafe fn close<T>(handle: *T, cb: *u8) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_close(handle as *c_void, cb);
}
pub unsafe fn walk(loop_handle: *c_void, cb: *u8, arg: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_walk(loop_handle, cb, arg);
}
pub unsafe fn idle_new() -> *uv_idle_t {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_idle_new()
}
pub unsafe fn idle_delete(handle: *uv_idle_t) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_idle_delete(handle)
}
pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_idle_init(loop_handle, handle)
}
pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_idle_start(handle, cb)
}
pub unsafe fn idle_stop(handle: *uv_idle_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_idle_stop(handle)
}
pub unsafe fn udp_init(loop_handle: *uv_loop_t, handle: *uv_udp_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_init(loop_handle, handle);
}
pub unsafe fn udp_bind(server: *uv_udp_t, addr: *sockaddr_in, flags: c_uint) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_bind(server, addr, flags);
}
pub unsafe fn udp_bind6(server: *uv_udp_t, addr: *sockaddr_in6, flags: c_uint) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_bind6(server, addr, flags);
}
pub unsafe fn udp_send<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
addr: *sockaddr_in, cb: uv_udp_send_cb) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
let buf_ptr = vec::raw::to_ptr(buf_in);
let buf_cnt = buf_in.len() as i32;
return rust_uv_udp_send(req, handle as *c_void, buf_ptr, buf_cnt, addr, cb);
@ -222,6 +261,8 @@ pub unsafe fn udp_send<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
pub unsafe fn udp_send6<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
addr: *sockaddr_in6, cb: uv_udp_send_cb) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
let buf_ptr = vec::raw::to_ptr(buf_in);
let buf_cnt = buf_in.len() as i32;
return rust_uv_udp_send6(req, handle as *c_void, buf_ptr, buf_cnt, addr, cb);
@ -229,124 +270,184 @@ pub unsafe fn udp_send6<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
pub unsafe fn udp_recv_start(server: *uv_udp_t, on_alloc: uv_alloc_cb,
on_recv: uv_udp_recv_cb) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_recv_start(server, on_alloc, on_recv);
}
pub unsafe fn udp_recv_stop(server: *uv_udp_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_recv_stop(server);
}
pub unsafe fn get_udp_handle_from_send_req(send_req: *uv_udp_send_t) -> *uv_udp_t {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_udp_handle_from_send_req(send_req);
}
pub unsafe fn udp_get_sockname(handle: *uv_udp_t, name: *sockaddr_storage) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_getsockname(handle, name);
}
pub unsafe fn udp_set_membership(handle: *uv_udp_t, multicast_addr: *c_char,
interface_addr: *c_char, membership: uv_membership) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_set_membership(handle, multicast_addr, interface_addr, membership as c_int);
}
pub unsafe fn udp_set_multicast_loop(handle: *uv_udp_t, on: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_set_multicast_loop(handle, on);
}
pub unsafe fn udp_set_multicast_ttl(handle: *uv_udp_t, ttl: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_set_multicast_ttl(handle, ttl);
}
pub unsafe fn udp_set_ttl(handle: *uv_udp_t, ttl: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_set_ttl(handle, ttl);
}
pub unsafe fn udp_set_broadcast(handle: *uv_udp_t, on: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_udp_set_broadcast(handle, on);
}
pub unsafe fn tcp_init(loop_handle: *c_void, handle: *uv_tcp_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_init(loop_handle, handle);
}
pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in, after_connect_cb: *u8) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr);
}
pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in6, after_connect_cb: *u8) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr);
}
pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_bind(tcp_server_ptr, addr_ptr);
}
pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in6) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr);
}
pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_storage) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_getpeername(tcp_handle_ptr, name);
}
pub unsafe fn tcp_getsockname(handle: *uv_tcp_t, name: *sockaddr_storage) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_getsockname(handle, name);
}
pub unsafe fn tcp_nodelay(handle: *uv_tcp_t, enable: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_nodelay(handle, enable);
}
pub unsafe fn tcp_keepalive(handle: *uv_tcp_t, enable: c_int, delay: c_uint) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_keepalive(handle, enable, delay);
}
pub unsafe fn tcp_simultaneous_accepts(handle: *uv_tcp_t, enable: c_int) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_tcp_simultaneous_accepts(handle, enable);
}
pub unsafe fn listen<T>(stream: *T, backlog: c_int, cb: *u8) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_listen(stream as *c_void, backlog, cb);
}
pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_accept(server as *c_void, client as *c_void);
}
pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
let buf_ptr = vec::raw::to_ptr(buf_in);
let buf_cnt = buf_in.len() as i32;
return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb);
}
pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: uv_alloc_cb, on_read: *u8) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_read_start(stream as *c_void, on_alloc, on_read);
}
pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_read_stop(stream as *c_void);
}
pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_last_error(loop_handle);
}
pub unsafe fn strerror(err: *uv_err_t) -> *c_char {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_strerror(err);
}
pub unsafe fn err_name(err: *uv_err_t) -> *c_char {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_err_name(err);
}
pub unsafe fn async_init(loop_handle: *c_void, async_handle: *uv_async_t, cb: *u8) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_async_init(loop_handle, async_handle, cb);
}
pub unsafe fn async_send(async_handle: *uv_async_t) {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_async_send(async_handle);
}
pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
#[fixed_stack_segment]; #[inline(never)];
let out_buf = uv_buf_t { base: ptr::null(), len: 0 as size_t };
let out_buf_ptr = ptr::to_unsafe_ptr(&out_buf);
rust_uv_buf_init(out_buf_ptr, input, len as size_t);
@ -354,99 +455,149 @@ pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
}
pub unsafe fn timer_init(loop_ptr: *c_void, timer_ptr: *uv_timer_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_timer_init(loop_ptr, timer_ptr);
}
pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: u64,
repeat: u64) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_timer_start(timer_ptr, cb, timeout, repeat);
}
pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_timer_stop(timer_ptr);
}
pub unsafe fn is_ip4_addr(addr: *sockaddr) -> bool {
#[fixed_stack_segment]; #[inline(never)];
match rust_uv_is_ipv4_sockaddr(addr) { 0 => false, _ => true }
}
pub unsafe fn is_ip6_addr(addr: *sockaddr) -> bool {
#[fixed_stack_segment]; #[inline(never)];
match rust_uv_is_ipv6_sockaddr(addr) { 0 => false, _ => true }
}
pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in {
#[fixed_stack_segment]; #[inline(never)];
do ip.with_c_str |ip_buf| {
rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int)
}
}
pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 {
#[fixed_stack_segment]; #[inline(never)];
do ip.with_c_str |ip_buf| {
rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int)
}
}
pub unsafe fn malloc_sockaddr_storage() -> *sockaddr_storage {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_malloc_sockaddr_storage()
}
pub unsafe fn free_sockaddr_storage(ss: *sockaddr_storage) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_free_sockaddr_storage(ss);
}
pub unsafe fn free_ip4_addr(addr: *sockaddr_in) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_free_ip4_addr(addr);
}
pub unsafe fn free_ip6_addr(addr: *sockaddr_in6) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_free_ip6_addr(addr);
}
pub unsafe fn ip4_name(addr: *sockaddr_in, dst: *u8, size: size_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_ip4_name(addr, dst, size);
}
pub unsafe fn ip6_name(addr: *sockaddr_in6, dst: *u8, size: size_t) -> c_int {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_ip6_name(addr, dst, size);
}
pub unsafe fn ip4_port(addr: *sockaddr_in) -> c_uint {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_ip4_port(addr);
}
pub unsafe fn ip6_port(addr: *sockaddr_in6) -> c_uint {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_ip6_port(addr);
}
// data access helpers
pub unsafe fn get_loop_for_uv_handle<T>(handle: *T) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_loop_for_uv_handle(handle as *c_void);
}
pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) -> *uv_stream_t {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_stream_handle_from_connect_req(connect);
}
pub unsafe fn get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_stream_handle_from_write_req(write_req);
}
pub unsafe fn get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_get_data_for_uv_loop(loop_ptr)
}
pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_set_data_for_uv_loop(loop_ptr, data);
}
pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_data_for_uv_handle(handle as *c_void);
}
pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_set_data_for_uv_handle(handle as *c_void, data as *c_void);
}
pub unsafe fn get_data_for_req<T>(req: *T) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_data_for_req(req as *c_void);
}
pub unsafe fn set_data_for_req<T, U>(req: *T, data: *U) {
#[fixed_stack_segment]; #[inline(never)];
rust_uv_set_data_for_req(req as *c_void, data as *c_void);
}
pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_base_from_buf(buf);
}
pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_len_from_buf(buf);
}
pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str {

View File

@ -147,8 +147,11 @@ impl Process {
* * options - Options to configure the environment of the process,
* the working directory and the standard IO streams.
*/
pub fn new(prog: &str, args: &[~str], options: ProcessOptions)
pub fn new(prog: &str, args: &[~str],
options: ProcessOptions)
-> Process {
#[fixed_stack_segment]; #[inline(never)];
let (in_pipe, in_fd) = match options.in_fd {
None => {
let pipe = os::pipe();
@ -287,6 +290,7 @@ impl Process {
* method does nothing.
*/
pub fn close_input(&mut self) {
#[fixed_stack_segment]; #[inline(never)];
match self.input {
Some(-1) | None => (),
Some(fd) => {
@ -299,10 +303,12 @@ impl Process {
}
fn close_outputs(&mut self) {
#[fixed_stack_segment]; #[inline(never)];
fclose_and_null(&mut self.output);
fclose_and_null(&mut self.error);
fn fclose_and_null(f_opt: &mut Option<*libc::FILE>) {
#[allow(cstack)]; // fixed_stack_segment declared on enclosing fn
match *f_opt {
Some(f) if !f.is_null() => {
unsafe {
@ -387,6 +393,7 @@ impl Process {
#[cfg(windows)]
fn killpid(pid: pid_t, _force: bool) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::funcs::extra::kernel32::TerminateProcess(
cast::transmute(pid), 1);
@ -395,6 +402,8 @@ impl Process {
#[cfg(unix)]
fn killpid(pid: pid_t, force: bool) {
#[fixed_stack_segment]; #[inline(never)];
let signal = if force {
libc::consts::os::posix88::SIGKILL
} else {
@ -447,6 +456,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
env: Option<~[(~str, ~str)]>,
dir: Option<&Path>,
in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
use libc::consts::os::extra::{
@ -630,6 +640,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
env: Option<~[(~str, ~str)]>,
dir: Option<&Path>,
in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
#[fixed_stack_segment]; #[inline(never)];
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
use libc::funcs::bsd44::getdtablesize;
@ -782,6 +793,7 @@ fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T {
#[cfg(windows)]
fn free_handle(handle: *()) {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle));
}
@ -848,6 +860,7 @@ fn waitpid(pid: pid_t) -> int {
#[cfg(windows)]
fn waitpid_os(pid: pid_t) -> int {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::DWORD;
use libc::consts::os::extra::{
@ -892,6 +905,7 @@ fn waitpid(pid: pid_t) -> int {
#[cfg(unix)]
fn waitpid_os(pid: pid_t) -> int {
#[fixed_stack_segment]; #[inline(never)];
use libc::funcs::posix01::wait::*;
@ -1069,6 +1083,8 @@ mod tests {
}
fn readclose(fd: c_int) -> ~str {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let file = os::fdopen(fd);
let reader = io::FILE_reader(file, false);
@ -1351,6 +1367,7 @@ mod tests {
}
fn running_on_valgrind() -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe { rust_running_on_valgrind() != 0 }
}

View File

@ -220,3 +220,4 @@ mod std {
pub use fmt;
pub use to_bytes;
}

View File

@ -2908,6 +2908,7 @@ mod tests {
#[test]
fn test_map() {
#[fixed_stack_segment]; #[inline(never)];
assert_eq!(~"", "".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char));
assert_eq!(~"YMCA", "ymca".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char));
}

View File

@ -147,7 +147,7 @@ pub unsafe fn local_pop<T: 'static>(handle: Handle,
// above.
let data = match util::replace(entry, None) {
Some((_, data, _)) => data,
None => libc::abort(),
None => abort(),
};
// Move `data` into transmute to get out the memory that it
@ -252,7 +252,7 @@ unsafe fn local_get_with<T: 'static, U>(handle: Handle,
}
}
}
_ => libc::abort()
_ => abort()
}
// n.b. 'data' and 'loans' are both invalid pointers at the point
@ -262,7 +262,7 @@ unsafe fn local_get_with<T: 'static, U>(handle: Handle,
if return_loan {
match map[i] {
Some((_, _, ref mut loan)) => { *loan = NoLoan; }
None => { libc::abort(); }
None => { abort(); }
}
}
return ret;
@ -270,6 +270,12 @@ unsafe fn local_get_with<T: 'static, U>(handle: Handle,
}
}
fn abort() -> ! {
#[fixed_stack_segment]; #[inline(never)];
unsafe { libc::abort() }
}
pub unsafe fn local_set<T: 'static>(handle: Handle,
key: local_data::Key<T>,
data: T) {

View File

@ -1045,15 +1045,12 @@ fn test_spawn_sched_childs_on_default_sched() {
mod testrt {
use libc;
#[nolink]
extern {
pub fn rust_dbg_lock_create() -> *libc::c_void;
pub fn rust_dbg_lock_destroy(lock: *libc::c_void);
pub fn rust_dbg_lock_lock(lock: *libc::c_void);
pub fn rust_dbg_lock_unlock(lock: *libc::c_void);
pub fn rust_dbg_lock_wait(lock: *libc::c_void);
pub fn rust_dbg_lock_signal(lock: *libc::c_void);
}
externfn!(fn rust_dbg_lock_create() -> *libc::c_void)
externfn!(fn rust_dbg_lock_destroy(lock: *libc::c_void))
externfn!(fn rust_dbg_lock_lock(lock: *libc::c_void))
externfn!(fn rust_dbg_lock_unlock(lock: *libc::c_void))
externfn!(fn rust_dbg_lock_wait(lock: *libc::c_void))
externfn!(fn rust_dbg_lock_signal(lock: *libc::c_void))
}
#[test]

View File

@ -145,16 +145,21 @@ mod dl {
use result::*;
pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
do filename.with_c_str |raw_name| {
dlopen(raw_name, Lazy as libc::c_int)
}
}
pub unsafe fn open_internal() -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
dlopen(ptr::null(), Lazy as libc::c_int)
}
pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do atomically {
let _old_error = dlerror();
@ -172,9 +177,13 @@ mod dl {
}
pub unsafe fn symbol(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
dlsym(handle, symbol)
}
pub unsafe fn close(handle: *libc::c_void) {
#[fixed_stack_segment]; #[inline(never)];
dlclose(handle); ()
}
@ -204,18 +213,21 @@ mod dl {
use result::*;
pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
do os::win32::as_utf16_p(filename.to_str()) |raw_name| {
LoadLibraryW(raw_name)
}
}
pub unsafe fn open_internal() -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
let handle = ptr::null();
GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
handle
}
pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do atomically {
SetLastError(0);
@ -232,9 +244,11 @@ mod dl {
}
}
pub unsafe fn symbol(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
GetProcAddress(handle, symbol)
}
pub unsafe fn close(handle: *libc::c_void) {
#[fixed_stack_segment]; #[inline(never)];
FreeLibrary(handle); ()
}

View File

@ -83,6 +83,8 @@ fn test_run_in_bare_thread_exchange() {
/// can lead to deadlock. Calling change_dir_locked recursively will
/// also deadlock.
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
#[fixed_stack_segment]; #[inline(never)];
use os;
use os::change_dir;
use unstable::sync::atomically;

View File

@ -322,7 +322,6 @@ impl LittleLock {
}
}
#[inline]
pub unsafe fn lock<T>(&self, f: &fn() -> T) -> T {
do atomically {
rust_lock_little_lock(self.l);
@ -410,13 +409,28 @@ impl<T:Send> Exclusive<T> {
}
}
extern {
fn rust_create_little_lock() -> rust_little_lock;
fn rust_destroy_little_lock(lock: rust_little_lock);
fn rust_lock_little_lock(lock: rust_little_lock);
fn rust_unlock_little_lock(lock: rust_little_lock);
#[cfg(stage0)]
mod macro_hack {
#[macro_escape];
macro_rules! externfn(
(fn $name:ident () $(-> $ret_ty:ty),*) => (
extern {
fn $name() $(-> $ret_ty),*;
}
);
(fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
extern {
fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
}
)
)
}
externfn!(fn rust_create_little_lock() -> rust_little_lock)
externfn!(fn rust_destroy_little_lock(lock: rust_little_lock))
externfn!(fn rust_lock_little_lock(lock: rust_little_lock))
externfn!(fn rust_unlock_little_lock(lock: rust_little_lock))
#[cfg(test)]
mod tests {
use cell::Cell;

View File

@ -968,6 +968,85 @@ pub fn std_macros() -> @str {
pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key;
)
)
// externfn! declares a wrapper for an external function.
// It is intended to be used like:
//
// externfn!(#[nolink]
// #[abi = \"cdecl\"]
// fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32)
//
// Due to limitations in the macro parser, this pattern must be
// implemented with 4 distinct patterns (with attrs / without
// attrs CROSS with args / without ARGS).
//
// Also, this macro grammar allows for any number of return types
// because I couldn't figure out the syntax to specify at most one.
macro_rules! externfn(
(fn $name:ident () $(-> $ret_ty:ty),*) => (
pub unsafe fn $name() $(-> $ret_ty),* {
// Note: to avoid obscure bug in macros, keep these
// attributes *internal* to the fn
#[fixed_stack_segment];
#[inline(never)];
#[allow(missing_doc)];
return $name();
extern {
fn $name() $(-> $ret_ty),*;
}
}
);
(fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
pub unsafe fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),* {
// Note: to avoid obscure bug in macros, keep these
// attributes *internal* to the fn
#[fixed_stack_segment];
#[inline(never)];
#[allow(missing_doc)];
return $name($($arg_name),*);
extern {
fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
}
}
);
($($attrs:attr)* fn $name:ident () $(-> $ret_ty:ty),*) => (
pub unsafe fn $name() $(-> $ret_ty),* {
// Note: to avoid obscure bug in macros, keep these
// attributes *internal* to the fn
#[fixed_stack_segment];
#[inline(never)];
#[allow(missing_doc)];
return $name();
$($attrs)*
extern {
fn $name() $(-> $ret_ty),*;
}
}
);
($($attrs:attr)* fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
pub unsafe fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),* {
// Note: to avoid obscure bug in macros, keep these
// attributes *internal* to the fn
#[fixed_stack_segment];
#[inline(never)];
#[allow(missing_doc)];
return $name($($arg_name),*);
$($attrs)*
extern {
fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
}
}
)
)
}";
}

View File

@ -24,6 +24,7 @@ pub mod rustrt {
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn fact(n: uint) -> uint {
unsafe {
info!("n = %?", n);

View File

@ -10,6 +10,7 @@
// Exercise the unused_unsafe attribute in some positive and negative cases
#[allow(cstack)];
#[deny(unused_unsafe)];
mod foo {
@ -55,6 +56,7 @@ fn good2() {
}
}
}
unsafe fn good3() { foo::bar() }
fn good4() { unsafe { foo::bar() } }

View File

@ -14,6 +14,7 @@ extern mod anonexternmod;
use anonexternmod::*;
#[fixed_stack_segment]
pub fn main() {
unsafe {
rust_get_test_int();

View File

@ -16,6 +16,7 @@ extern {
fn rust_get_test_int() -> libc::intptr_t;
}
#[fixed_stack_segment]
pub fn main() {
unsafe {
let _ = rust_get_test_int();

View File

@ -19,10 +19,12 @@ mod libc {
}
}
#[fixed_stack_segment]
fn atol(s: ~str) -> int {
s.with_c_str(|x| unsafe { libc::atol(x) as int })
}
#[fixed_stack_segment]
fn atoll(s: ~str) -> i64 {
s.with_c_str(|x| unsafe { libc::atoll(x) as i64 })
}

View File

@ -27,6 +27,7 @@ extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
}
}
#[fixed_stack_segment]
fn count(n: uint) -> uint {
unsafe {
info!("n = %?", n);

View File

@ -28,6 +28,7 @@ extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
}
}
#[fixed_stack_segment] #[inline(never)]
fn count(n: uint) -> uint {
unsafe {
info!("n = %?", n);

View File

@ -32,6 +32,7 @@ extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
}
}
#[fixed_stack_segment] #[inline(never)]
fn count(n: uint) -> uint {
unsafe {
info!("n = %?", n);

View File

@ -27,6 +27,7 @@ extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
}
}
#[fixed_stack_segment] #[inline(never)]
fn fact(n: uint) -> uint {
unsafe {
info!("n = %?", n);

View File

@ -13,6 +13,7 @@
extern mod externcallback(vers = "0.1");
#[fixed_stack_segment] #[inline(never)]
fn fact(n: uint) -> uint {
unsafe {
info!("n = %?", n);

View File

@ -20,6 +20,7 @@ extern {
pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let x = TwoU32s {one: 22, two: 23};

View File

@ -19,6 +19,7 @@ extern {
pub fn rust_dbg_extern_identity_TwoU64s(u: TwoU64s) -> TwoU64s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let x = TwoU64s {one: 22, two: 23};

View File

@ -24,6 +24,7 @@ extern {
pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let x = TwoU64s {one: 22, two: 23};

View File

@ -14,6 +14,7 @@ extern {
pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
assert_eq!(22_u8, rust_dbg_extern_identity_u8(22_u8));

View File

@ -12,6 +12,7 @@ extern {
pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64));

View File

@ -14,6 +14,7 @@ extern {
pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
assert_eq!(22_u32, rust_dbg_extern_identity_u32(22_u32));

View File

@ -14,6 +14,7 @@ extern {
pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
assert_eq!(22_u64, rust_dbg_extern_identity_u64(22_u64));

View File

@ -16,6 +16,7 @@ extern {
pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let y = rust_dbg_extern_return_TwoU16s();

View File

@ -16,6 +16,7 @@ extern {
pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let y = rust_dbg_extern_return_TwoU32s();

View File

@ -16,6 +16,7 @@ extern {
pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let y = rust_dbg_extern_return_TwoU64s();

View File

@ -16,6 +16,7 @@ extern {
pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let y = rust_dbg_extern_return_TwoU8s();

View File

@ -32,6 +32,7 @@ extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
}
}
#[fixed_stack_segment] #[inline(never)]
fn count(n: uint) -> uint {
unsafe {
rustrt::rust_dbg_call(cb, n)

View File

@ -28,6 +28,7 @@ extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
}
}
#[fixed_stack_segment] #[inline(never)]
fn count(n: uint) -> uint {
unsafe {
task::deschedule();

View File

@ -2,9 +2,7 @@ use std::cast;
use std::libc;
use std::unstable::run_in_bare_thread;
extern {
pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) -> libc::uintptr_t;
}
externfn!(fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) -> libc::uintptr_t)
pub fn main() {
unsafe {

View File

@ -31,6 +31,7 @@ mod rustrt2 {
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
rustrt1::rust_get_test_int();

View File

@ -21,6 +21,7 @@ mod libc {
}
}
#[fixed_stack_segment] #[inline(never)]
fn strlen(str: ~str) -> uint {
// C string is terminated with a zero
do str.with_c_str |buf| {

View File

@ -18,6 +18,7 @@ mod rustrt {
}
}
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
rustrt::rust_get_test_int();

View File

@ -17,6 +17,7 @@
extern mod foreign_lib;
#[fixed_stack_segment] #[inline(never)]
pub fn main() {
unsafe {
let _foo = foreign_lib::rustrt::rust_get_test_int();

View File

@ -19,6 +19,7 @@ fn to_c_int(v: &mut int) -> &mut c_int {
}
}
#[fixed_stack_segment] #[inline(never)]
fn lgamma(n: c_double, value: &mut int) -> c_double {
unsafe {
return m::lgamma(n, to_c_int(value));

View File

@ -4,6 +4,7 @@ use std::libc;
pub struct Fd(c_int);
impl Drop for Fd {
#[fixed_stack_segment] #[inline(never)]
fn drop(&self) {
unsafe {
libc::close(**self);

View File

@ -6,6 +6,7 @@ mod a {
}
}
#[fixed_stack_segment] #[inline(never)]
fn main() {
unsafe {
a::free(transmute(0));

View File

@ -27,6 +27,7 @@ struct Ccx {
x: int
}
#[fixed_stack_segment] #[inline(never)]
fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
unsafe {
cast::transmute(libc::malloc(sys::size_of::<Bcx<'blk>>()
@ -38,6 +39,7 @@ fn h<'a>(bcx : &'a Bcx<'a>) -> &'a Bcx<'a> {
return alloc(bcx.fcx.arena);
}
#[fixed_stack_segment] #[inline(never)]
fn g(fcx : &Fcx) {
let bcx = Bcx { fcx: fcx };
let bcx2 = h(&bcx);

View File

@ -26,6 +26,7 @@ fn static_bound_set(a: &'static mut libc::c_int) {
*a = 3;
}
#[fixed_stack_segment] #[inline(never)]
unsafe fn run() {
assert!(debug_static_mut == 3);
debug_static_mut = 4;

View File

@ -21,6 +21,7 @@ mod rustrt {
}
}
#[fixed_stack_segment] #[inline(never)]
fn test1() {
unsafe {
let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa_u64,
@ -40,6 +41,8 @@ fn test1() {
}
#[cfg(target_arch = "x86_64")]
#[fixed_stack_segment]
#[inline(never)]
fn test2() {
unsafe {
let f = Floats { a: 1.234567890e-15_f64,

View File

@ -29,6 +29,7 @@ mod kernel32 {
#[cfg(target_os = "win32")]
#[fixed_stack_segment]
pub fn main() {
let heap = unsafe { kernel32::GetProcessHeap() };
let mem = unsafe { kernel32::HeapAlloc(heap, 0u32, 100u32) };