1
Fork 0

auto merge of #5322 : brson/rust/4812, r=brson

Supersedes #5013
This commit is contained in:
bors 2013-03-11 16:39:43 -07:00
commit f4dba956ec
11 changed files with 382 additions and 149 deletions

View file

@ -58,6 +58,7 @@ Implicitly, all crates behave as if they included the following prologue:
#[cfg(target_os = "linux")]
pub mod linkhack {
#[link_args="-lrustrt -lrt"]
#[link_args = "-lpthread"]
extern {
}
}

View file

@ -534,6 +534,8 @@ pub mod types {
pub type LPCWSTR = *WCHAR;
pub type LPCSTR = *CHAR;
pub type LPCTSTR = *CHAR;
pub type LPTCH = *CHAR;
pub type LPWSTR = *mut WCHAR;
pub type LPSTR = *mut CHAR;
@ -792,6 +794,7 @@ pub mod consts {
pub const ERROR_SUCCESS : int = 0;
pub const ERROR_INSUFFICIENT_BUFFER : int = 122;
pub const INVALID_HANDLE_VALUE: int = -1;
}
}
@ -1115,6 +1118,7 @@ pub mod funcs {
pub mod string {
use libc::types::common::c95::c_void;
use libc::types::os::arch::c95::{c_char, c_int, size_t};
use libc::types::os::arch::c95::{wchar_t};
pub extern {
unsafe fn strcpy(dst: *c_char, src: *c_char) -> *c_char;
@ -1138,6 +1142,7 @@ pub mod funcs {
unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char;
unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t)
-> size_t;
unsafe fn wcslen(buf: *wchar_t) -> size_t;
// These are fine to execute on the Rust stack. They must be,
// in fact, because LLVM generates calls to them!
@ -1381,9 +1386,28 @@ pub mod funcs {
use libc::types::os::arch::c95::{c_char, c_int, c_long};
pub extern {
// default bindings for opendir and readdir in
// non-macos unix
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
unsafe fn opendir(dirname: *c_char) -> *DIR;
unsafe fn closedir(dirp: *DIR) -> c_int;
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
unsafe fn readdir(dirp: *DIR) -> *dirent_t;
// on OSX (particularly when running with a
// 64bit kernel), we have an issue where there
// are separate bindings for opendir and readdir,
// which we have to explicitly link, as below.
#[cfg(target_os = "macos")]
#[link_name = "opendir$INODE64"]
unsafe fn opendir(dirname: *c_char) -> *DIR;
#[cfg(target_os = "macos")]
#[link_name = "readdir$INODE64"]
unsafe fn readdir(dirp: *DIR) -> *dirent_t;
unsafe fn closedir(dirp: *DIR) -> c_int;
unsafe fn rewinddir(dirp: *DIR);
unsafe fn seekdir(dirp: *DIR, loc: c_long);
unsafe fn telldir(dirp: *DIR) -> c_long;
@ -1594,8 +1618,9 @@ pub mod funcs {
pub mod kernel32 {
use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE};
use libc::types::os::arch::extra::{LPCWSTR, LPWSTR};
use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPTCH};
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES};
use libc::types::os::arch::extra::{HANDLE};
#[abi = "stdcall"]
pub extern {
@ -1605,6 +1630,8 @@ pub mod funcs {
-> DWORD;
unsafe fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
-> BOOL;
unsafe fn GetEnvironmentStringsA() -> LPTCH;
unsafe fn FreeEnvironmentStringsA(env_ptr: LPTCH) -> BOOL;
unsafe fn GetModuleFileNameW(hModule: HMODULE,
lpFilename: LPWSTR,
@ -1623,6 +1650,13 @@ pub mod funcs {
unsafe fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
unsafe fn GetLastError() -> DWORD;
unsafe fn FindFirstFileW(fileName: *u16,
findFileData: HANDLE)
-> HANDLE;
unsafe fn FindNextFileW(findFile: HANDLE,
findFileData: HANDLE)
-> BOOL;
unsafe fn FindClose(findFile: HANDLE) -> BOOL;
}
}

View file

@ -58,20 +58,25 @@ pub mod rustrt {
pub extern {
unsafe fn rust_get_argc() -> c_int;
unsafe fn rust_get_argv() -> **c_char;
unsafe fn rust_getcwd() -> ~str;
unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int;
unsafe fn rust_path_exists(path: *libc::c_char) -> c_int;
unsafe fn rust_list_files2(&&path: ~str) -> ~[~str];
unsafe fn rust_process_wait(handle: c_int) -> c_int;
unsafe fn rust_set_exit_status(code: libc::intptr_t);
}
}
pub const TMPBUF_SZ : uint = 1000u;
const BUF_BYTES : uint = 2048u;
pub fn getcwd() -> Path {
let buf = [0 as libc::c_char, ..BUF_BYTES];
unsafe {
Path(rustrt::rust_getcwd())
if(0 as *libc::c_char == libc::getcwd(
&buf[0],
BUF_BYTES as libc::size_t)) {
fail!();
}
Path(str::raw::from_c_str(&buf[0]))
}
}
@ -164,20 +169,68 @@ fn with_env_lock<T>(f: &fn() -> T) -> T {
}
pub fn env() -> ~[(~str,~str)] {
extern {
unsafe fn rust_env_pairs() -> ~[~str];
}
unsafe {
do with_env_lock {
#[cfg(windows)]
unsafe fn get_env_pairs() -> ~[~str] {
use libc::types::os::arch::extra::LPTCH;
use libc::funcs::extra::kernel32::{
GetEnvironmentStringsA,
FreeEnvironmentStringsA
};
let ch = GetEnvironmentStringsA();
if (ch as uint == 0) {
fail!(fmt!("os::env() failure getting env string from OS: %s",
os::last_os_error()));
}
let mut curr_ptr: uint = ch as uint;
let mut result = ~[];
while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
let env_pair = str::raw::from_c_str(
curr_ptr as *libc::c_char);
result.push(env_pair);
curr_ptr +=
libc::strlen(curr_ptr as *libc::c_char) as uint
+ 1;
}
FreeEnvironmentStringsA(ch);
result
}
#[cfg(unix)]
unsafe fn get_env_pairs() -> ~[~str] {
extern mod rustrt {
unsafe fn rust_env_pairs() -> **libc::c_char;
}
let environ = rustrt::rust_env_pairs();
if (environ as uint == 0) {
fail!(fmt!("os::env() failure getting env string from OS: %s",
os::last_os_error()));
}
let mut result = ~[];
ptr::array_each(environ, |e| {
let env_pair = str::raw::from_c_str(e);
log(debug, fmt!("get_env_pairs: %s",
env_pair));
result.push(env_pair);
});
result
}
fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
let mut pairs = ~[];
for vec::each(rust_env_pairs()) |p| {
let vs = str::splitn_char(*p, '=', 1u);
fail_unless!(vec::len(vs) == 2u);
for input.each |p| {
let vs = str::splitn_char(*p, '=', 1);
log(debug,
fmt!("splitting: len: %u",
vs.len()));
fail_unless!(vs.len() == 2);
pairs.push((copy vs[0], copy vs[1]));
}
pairs
}
do with_env_lock {
let unparsed_environ = get_env_pairs();
env_convert(unparsed_environ)
}
}
}
@ -615,13 +668,97 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
#[allow(non_implicitly_copyable_typarams)]
pub fn list_dir(p: &Path) -> ~[~str] {
unsafe {
#[cfg(unix)]
fn star(p: &Path) -> Path { copy *p }
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
unsafe fn get_list(p: &Path) -> ~[~str] {
use libc::{DIR, dirent_t};
use libc::{opendir, readdir, closedir};
extern mod rustrt {
unsafe fn rust_list_dir_val(ptr: *dirent_t)
-> *libc::c_char;
}
let input = p.to_str();
let mut strings = ~[];
let input_ptr = ::cast::transmute(&input[0]);
log(debug, "os::list_dir -- BEFORE OPENDIR");
let dir_ptr = opendir(input_ptr);
if (dir_ptr as uint != 0) {
log(debug, "os::list_dir -- opendir() SUCCESS");
let mut entry_ptr = readdir(dir_ptr);
while (entry_ptr as uint != 0) {
strings.push(
str::raw::from_c_str(
rustrt::rust_list_dir_val(
entry_ptr)));
entry_ptr = readdir(dir_ptr);
}
closedir(dir_ptr);
}
else {
log(debug, "os::list_dir -- opendir() FAILURE");
}
log(debug,
fmt!("os::list_dir -- AFTER -- #: %?",
strings.len()));
strings
}
#[cfg(windows)]
fn star(p: &Path) -> Path { p.push("*") }
do rustrt::rust_list_files2(star(p).to_str()).filtered |filename| {
unsafe fn get_list(p: &Path) -> ~[~str] {
use libc::types::os::arch::extra::{LPCTSTR, HANDLE, BOOL};
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
use libc::wcslen;
use libc::funcs::extra::kernel32::{
FindFirstFileW,
FindNextFileW,
FindClose,
};
use os::win32::{
as_utf16_p
};
use unstable::exchange_alloc::{malloc_raw, free_raw};
#[nolink]
extern mod rustrt {
unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void)
-> *u16;
}
fn star(p: &Path) -> Path { p.push("*") }
do as_utf16_p(star(p).to_str()) |path_ptr| {
let mut strings = ~[];
let wfd_ptr = malloc_raw(
rustrt::rust_list_dir_wfd_size() as uint);
let find_handle =
FindFirstFileW(
path_ptr,
::cast::transmute(wfd_ptr));
if find_handle as int != INVALID_HANDLE_VALUE {
let mut more_files = 1 as libc::c_int;
while more_files != 0 {
let fp_buf = rustrt::rust_list_dir_wfd_fp_buf(
wfd_ptr);
if fp_buf as uint == 0 {
fail!(~"os::list_dir() failure:"+
~" got null ptr from wfd");
}
else {
let fp_vec = vec::from_buf(
fp_buf, wcslen(fp_buf) as uint);
let fp_str = str::from_utf16(fp_vec);
strings.push(fp_str);
}
more_files = FindNextFileW(
find_handle,
::cast::transmute(wfd_ptr));
}
FindClose(find_handle);
free_raw(wfd_ptr);
}
strings
}
}
do get_list(p).filtered |filename| {
*filename != ~"." && *filename != ~".."
}
}
@ -1274,9 +1411,8 @@ mod tests {
setenv(~"USERPROFILE", ~"/home/PaloAlto");
fail_unless!(os::homedir() == Some(Path("/home/MountainView")));
option::iter(&oldhome, |s| setenv(~"HOME", *s));
option::iter(&olduserprofile,
|s| setenv(~"USERPROFILE", *s));
oldhome.each(|s| {setenv(~"HOME", *s);true});
olduserprofile.each(|s| {setenv(~"USERPROFILE", *s);true});
}
#[test]

View file

@ -19,6 +19,8 @@ use sys;
#[cfg(test)] use vec;
#[cfg(test)] use str;
#[cfg(notest)] use cmp::{Eq, Ord};
use debug;
use uint;
pub mod libc_ {
use libc::c_void;
@ -181,6 +183,46 @@ pub pure fn ref_eq<T>(thing: &a/T, other: &b/T) -> bool {
to_uint(thing) == to_uint(other)
}
/**
Given a **T (pointer to an array of pointers),
iterate through each *T, up to the provided `len`,
passing to the provided callback function
SAFETY NOTE: Pointer-arithmetic. Dragons be here.
*/
pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
log(debug, "array_each_with_len: before iterate");
if (arr as uint == 0) {
fail!(~"ptr::array_each_with_len failure: arr input is null pointer");
}
//let start_ptr = *arr;
uint::iterate(0, len, |e| {
let n = offset(arr, e);
cb(*n);
true
});
log(debug, "array_each_with_len: after iterate");
}
/**
Given a null-pointer-terminated **T (pointer to
an array of pointers), iterate through each *T,
passing to the provided callback function
SAFETY NOTE: This will only work with a null-terminated
pointer array. Barely less-dodgey Pointer Arithmetic.
Dragons be here.
*/
pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
if (arr as uint == 0) {
fail!(~"ptr::array_each_with_len failure: arr input is null pointer");
}
let len = buf_len(arr);
log(debug, fmt!("array_each inferred len: %u",
len));
array_each_with_len(arr, len, cb);
}
pub trait Ptr<T> {
pure fn is_null(&self) -> bool;
pure fn is_not_null(&self) -> bool;
@ -389,3 +431,95 @@ pub fn test_is_null() {
fail_unless!(!mq.is_null());
fail_unless!(mq.is_not_null());
}
#[cfg(test)]
pub mod ptr_tests {
use debug;
use ptr;
use str;
use libc;
use vec;
#[test]
pub fn test_ptr_array_each_with_len() {
unsafe {
let one = ~"oneOne";
let two = ~"twoTwo";
let three = ~"threeThree";
let arr: ~[*i8] = ~[
::cast::transmute(&one[0]),
::cast::transmute(&two[0]),
::cast::transmute(&three[0]),
];
let expected_arr = [
one, two, three
];
let arr_ptr = &arr[0];
let mut ctr = 0;
let mut iteration_count = 0;
ptr::array_each_with_len(arr_ptr, vec::len(arr),
|e| {
let actual = str::raw::from_c_str(e);
let expected = copy expected_arr[ctr];
log(debug,
fmt!("test_ptr_array_each e: %s, a: %s",
expected, actual));
fail_unless!(actual == expected);
ctr += 1;
iteration_count += 1;
});
fail_unless!(iteration_count == 3u);
}
}
#[test]
pub fn test_ptr_array_each() {
unsafe {
let one = ~"oneOne";
let two = ~"twoTwo";
let three = ~"threeThree";
let arr: ~[*i8] = ~[
::cast::transmute(&one[0]),
::cast::transmute(&two[0]),
::cast::transmute(&three[0]),
// fake a null terminator
0 as *i8
];
let expected_arr = [
one, two, three
];
let arr_ptr = &arr[0];
let mut ctr = 0;
let mut iteration_count = 0;
ptr::array_each(arr_ptr, |e| {
let actual = str::raw::from_c_str(e);
let expected = copy expected_arr[ctr];
log(debug,
fmt!("test_ptr_array_each e: %s, a: %s",
expected, actual));
fail_unless!(actual == expected);
ctr += 1;
iteration_count += 1;
});
fail_unless!(iteration_count == 3);
}
}
#[test]
#[should_fail]
#[ignore(cfg(windows))]
pub fn test_ptr_array_each_with_len_null_ptr() {
unsafe {
ptr::array_each_with_len(0 as **libc::c_char, 1, |e| {
str::raw::from_c_str(e);
});
}
}
#[test]
#[should_fail]
#[ignore(cfg(windows))]
pub fn test_ptr_array_each_null_ptr() {
unsafe {
ptr::array_each(0 as **libc::c_char, |e| {
str::raw::from_c_str(e);
});
}
}
}

View file

@ -41,6 +41,17 @@ pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
return transmute(box);
}
}
/**
Thin wrapper around libc::malloc, none of the box header
stuff in exchange_alloc::malloc
*/
pub unsafe fn malloc_raw(size: uint) -> *c_void {
let p = c_malloc(size as size_t);
if p.is_null() {
fail!(~"Failure in malloc_raw: result ptr is null");
}
p
}
pub unsafe fn free(ptr: *c_void) {
let exchange_count = &mut *rust_get_exchange_count_ptr();
@ -49,6 +60,10 @@ pub unsafe fn free(ptr: *c_void) {
fail_unless!(ptr.is_not_null());
c_free(ptr);
}
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
pub unsafe fn free_raw(ptr: *c_void) {
c_free(ptr);
}
fn get_box_size(body_size: uint, body_align: uint) -> uint {
let header_size = size_of::<BoxHeaderRepr>();

View file

@ -2692,6 +2692,7 @@ mod tests {
#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_last_empty() {
let a: ~[int] = ~[];
a.last();

View file

@ -52,64 +52,18 @@ timegm(struct tm *tm)
}
#endif
extern "C" CDECL rust_str *
rust_getcwd() {
rust_task *task = rust_get_current_task();
LOG(task, task, "rust_getcwd()");
char cbuf[BUF_BYTES];
#if defined(__WIN32__)
if (!_getcwd(cbuf, sizeof(cbuf))) {
#else
if (!getcwd(cbuf, sizeof(cbuf))) {
#endif
task->fail();
return NULL;
}
return make_str(task->kernel, cbuf, strlen(cbuf), "rust_str(getcwd)");
}
#if defined(__WIN32__)
extern "C" CDECL rust_vec_box *
extern "C" CDECL char**
rust_env_pairs() {
rust_task *task = rust_get_current_task();
size_t envc = 0;
LPTCH ch = GetEnvironmentStringsA();
LPTCH c;
for (c = ch; *c; c += strlen(c) + 1) {
++envc;
}
c = ch;
rust_vec_box *v = (rust_vec_box *)
task->kernel->malloc(vec_size<rust_vec_box*>(envc),
"str vec interior");
v->body.fill = v->body.alloc = sizeof(rust_vec*) * envc;
for (size_t i = 0; i < envc; ++i) {
size_t n = strlen(c);
rust_str *str = make_str(task->kernel, c, n, "str");
((rust_str**)&v->body.data)[i] = str;
c += n + 1;
}
if (ch) {
FreeEnvironmentStrings(ch);
}
return v;
return 0;
}
#else
extern "C" CDECL rust_vec_box *
extern "C" CDECL char**
rust_env_pairs() {
rust_task *task = rust_get_current_task();
#ifdef __APPLE__
char **environ = *_NSGetEnviron();
#endif
char **e = environ;
size_t envc = 0;
while (*e) {
++envc; ++e;
}
return make_str_vec(task->kernel, envc, environ);
return environ;
}
#endif
@ -293,49 +247,43 @@ debug_get_stk_seg() {
return task->stk;
}
extern "C" CDECL rust_vec_box*
rust_list_files(rust_str *path) {
rust_task *task = rust_get_current_task();
array_list<rust_str*> strings;
extern "C" CDECL char*
#if defined(__WIN32__)
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile((char*)path->body.data, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
rust_str *str = make_str(task->kernel, FindFileData.cFileName,
strlen(FindFileData.cFileName),
"list_files_str");
strings.push(str);
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
return entry_ptr->cFileName;
}
#else
DIR *dirp = opendir((char*)path->body.data);
if (dirp) {
struct dirent *dp;
while ((dp = readdir(dirp))) {
rust_vec_box *str = make_str(task->kernel, dp->d_name,
strlen(dp->d_name),
"list_files_str");
strings.push(str);
}
closedir(dirp);
}
rust_list_dir_val(dirent* entry_ptr) {
return entry_ptr->d_name;
}
#endif
rust_vec_box *vec = (rust_vec_box *)
task->kernel->malloc(vec_size<rust_vec_box*>(strings.size()),
"list_files_vec");
size_t alloc_sz = sizeof(rust_vec*) * strings.size();
vec->body.fill = vec->body.alloc = alloc_sz;
memcpy(&vec->body.data[0], strings.data(), alloc_sz);
return vec;
extern "C" CDECL size_t
#if defined(__WIN32__)
rust_list_dir_wfd_size() {
return sizeof(WIN32_FIND_DATAW);
}
#else
rust_list_dir_wfd_size() {
return 0;
}
#endif
extern "C" CDECL rust_vec_box*
rust_list_files2(rust_str **path) {
return rust_list_files(*path);
extern "C" CDECL void*
#if defined(__WIN32__)
rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) {
if(wfd == NULL) {
return 0;
}
else {
return wfd->cFileName;
}
}
#else
rust_list_dir_wfd_fp_buf(void* wfd) {
return 0;
}
#endif
extern "C" CDECL int
rust_path_is_dir(char *path) {

View file

@ -79,38 +79,6 @@ inline void reserve_vec_exact(rust_vec_box** vpp,
typedef rust_vec_box rust_str;
inline rust_str *
make_str(rust_kernel* kernel, const char* c, size_t strlen,
const char* name) {
size_t str_fill = strlen + 1;
size_t str_alloc = str_fill;
rust_str *str = (rust_str *)
kernel->malloc(vec_size<char>(str_fill), name);
str->header.td = &str_body_tydesc;
str->body.fill = str_fill;
str->body.alloc = str_alloc;
memcpy(&str->body.data, c, strlen);
str->body.data[strlen] = '\0';
return str;
}
inline rust_vec_box *
make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) {
rust_vec_box *v = (rust_vec_box *)
kernel->malloc(vec_size<rust_vec_box*>(nstrs),
"str vec interior");
// FIXME: should have a real td (Issue #2639)
v->header.td = NULL;
v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs;
for (size_t i = 0; i < nstrs; ++i) {
rust_str *str = make_str(kernel, strs[i],
strlen(strs[i]),
"str");
((rust_str**)&v->body.data)[i] = str;
}
return v;
}
inline size_t get_box_size(size_t body_size, size_t body_align) {
size_t header_size = sizeof(rust_opaque_box);
// FIXME (#2699): This alignment calculation is suspicious. Is it right?

View file

@ -29,12 +29,12 @@ rust_new_task_in_sched
rust_num_threads
rust_path_is_dir
rust_path_exists
rust_getcwd
rust_get_stdin
rust_get_stdout
rust_get_stderr
rust_list_files
rust_list_files2
rust_list_dir_val
rust_list_dir_wfd_size
rust_list_dir_wfd_fp_buf
rust_log_console_on
rust_log_console_off
rust_process_wait
@ -43,7 +43,6 @@ rust_sched_current_nonlazy_threads
rust_sched_threads
rust_set_exit_status
rust_start
rust_getcwd
rust_env_pairs
rust_task_yield
rust_task_is_unwinding

View file

@ -112,8 +112,8 @@ mod test_foreign_items {
#[abi = "cdecl"]
pub extern {
#[cfg(bogus)]
pub fn rust_getcwd() -> ~str;
pub fn rust_getcwd() -> ~str;
pub fn rust_get_stdin() -> ~str;
pub fn rust_get_stdin() -> ~str;
}
}
}

View file

@ -17,7 +17,6 @@ mod rustrt {
pub fn rust_get_sched_id() -> libc::intptr_t;
pub fn rust_get_argc() -> libc::c_int;
pub fn rust_getcwd() -> ~str;
pub fn get_task_id() -> libc::intptr_t;
pub fn rust_sched_threads();
pub fn rust_get_task();
@ -26,7 +25,6 @@ mod rustrt {
fn calllink01() { unsafe { rustrt::rust_get_sched_id(); } }
fn calllink02() { unsafe { rustrt::rust_get_argc(); } }
fn calllink03() { unsafe { rustrt::rust_getcwd(); } }
fn calllink08() { unsafe { rustrt::get_task_id(); } }
fn calllink09() { unsafe { rustrt::rust_sched_threads(); } }
fn calllink10() { unsafe { rustrt::rust_get_task(); } }
@ -59,7 +57,6 @@ pub fn main() {
let fns = ~[
calllink01,
calllink02,
calllink03,
calllink08,
calllink09,
calllink10