From 95b3689b34035a0c3d7831441c1eae0904903351 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 5 Aug 2013 21:15:55 +0400 Subject: Implement FromStr for IpAddr and SocketAddr Better than that in rt::uv::net, because it: * handles invalid input explicitly, without fail!() * parses socket address, not just IP * handles various ipv4-in-ipv6 addresses, like 2001:db8:122:344::192.0.2.33 (see http://tools.ietf.org/html/rfc6052 for example) * rejects output like `127.0000000.0.1` * does not allocate heap memory * have unit tests --- src/libstd/rt/io/net/ip.rs | 365 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) (limited to 'src/libstd/rt') diff --git a/src/libstd/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs index 815ec9b5c61..81269d197d5 100644 --- a/src/libstd/rt/io/net/ip.rs +++ b/src/libstd/rt/io/net/ip.rs @@ -9,7 +9,11 @@ // except according to those terms. use num::FromStrRadix; +use vec::MutableCloneableVector; use to_str::ToStr; +use from_str::FromStr; +use option::{Option, None, Some}; + type Port = u16; @@ -73,3 +77,364 @@ impl ToStr for SocketAddr { } } } + +struct Parser<'self> { + // parsing as ASCII, so can use byte array + s: &'self [u8], + pos: uint, +} + +impl<'self> Parser<'self> { + fn new(s: &'self str) -> Parser<'self> { + Parser { + s: s.as_bytes(), + pos: 0, + } + } + + fn is_eof(&self) -> bool { + self.pos == self.s.len() + } + + // Commit only if parser returns Some + fn read_atomically(&mut self, cb: &fn(&mut Parser) -> Option) -> Option { + let pos = self.pos; + let r = cb(self); + if r.is_none() { + self.pos = pos; + } + r + } + + // Commit only if parser read till EOF + fn read_till_eof(&mut self, cb: &fn(&mut Parser) -> Option) -> Option { + do self.read_atomically |p| { + cb(p).filtered(|_| p.is_eof()) + } + } + + // Return result of first successful parser + fn read_or(&mut self, parsers: &[&fn(&mut Parser) -> Option]) -> Option { + for pf in parsers.iter() { + match self.read_atomically(|p: &mut Parser| (*pf)(p)) { + Some(r) => return Some(r), + None => {} + } + } + None + } + + // Apply 3 parsers sequentially + fn read_seq_3(&mut self, + pa: &fn(&mut Parser) -> Option, + pb: &fn(&mut Parser) -> Option, + pc: &fn(&mut Parser) -> Option + ) -> Option<(A, B, C)> + { + do self.read_atomically |p| { + let a = pa(p); + let b = if a.is_some() { pb(p) } else { None }; + let c = if b.is_some() { pc(p) } else { None }; + match (a, b, c) { + (Some(a), Some(b), Some(c)) => Some((a, b, c)), + _ => None + } + } + } + + // Read next char + fn read_char(&mut self) -> Option { + if self.is_eof() { + None + } else { + let r = self.s[self.pos] as char; + self.pos += 1; + Some(r) + } + } + + // Return char and advance iff next char is equal to requested + fn read_given_char(&mut self, c: char) -> Option { + do self.read_atomically |p| { + p.read_char().filtered(|&next| next == c) + } + } + + // Read digit + fn read_digit(&mut self, radix: u8) -> Option { + fn parse_digit(c: char, radix: u8) -> Option { + // assuming radix is either 10 or 16 + if c >= '0' && c <= '9' { + Some((c - '0') as u8) + } else if radix > 10 && c >= 'a' && c < 'a' + (radix - 10) as char { + Some((c - 'a' + (10 as char)) as u8) + } else if radix > 10 && c >= 'A' && c < 'A' + (radix - 10) as char { + Some((c - 'A' + (10 as char)) as u8) + } else { + None + } + } + + do self.read_atomically |p| { + p.read_char().chain(|c| parse_digit(c, radix)) + } + } + + fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option { + let mut r = 0u32; + let mut digit_count = 0; + loop { + match self.read_digit(radix) { + Some(d) => { + r = r * (radix as u32) + (d as u32); + digit_count += 1; + if digit_count > max_digits || r >= upto { + return None + } + } + None => { + if digit_count == 0 { + return None + } else { + return Some(r) + } + } + }; + } + } + + // Read number, failing if max_digits of number value exceeded + fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option { + do self.read_atomically |p| { + p.read_number_impl(radix, max_digits, upto) + } + } + + fn read_ipv4_addr_impl(&mut self) -> Option { + let mut bs = [0u8, ..4]; + let mut i = 0; + while i < 4 { + if i != 0 && self.read_given_char('.').is_none() { + return None; + } + + let octet = self.read_number(10, 3, 0x100).map(|&n| n as u8); + match octet { + Some(d) => bs[i] = d, + None => return None, + }; + i += 1; + } + Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3])) + } + + // Read IPv4 address + fn read_ipv4_addr(&mut self) -> Option { + do self.read_atomically |p| { + p.read_ipv4_addr_impl() + } + } + + fn read_ipv6_addr_impl(&mut self) -> Option { + fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr { + assert!(head.len() + tail.len() <= 8); + let mut gs = [0u16, ..8]; + gs.copy_from(head); + gs.mut_slice(8 - tail.len(), 8).copy_from(tail); + Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) + } + + fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) { + let mut i = 0; + while i < limit { + if i < limit - 1 { + let ipv4 = do p.read_atomically |p| { + if i == 0 || p.read_given_char(':').is_some() { + p.read_ipv4_addr() + } else { + None + } + }; + match ipv4 { + Some(Ipv4Addr(a, b, c, d)) => { + groups[i + 0] = (a as u16 << 8) | (b as u16); + groups[i + 1] = (c as u16 << 8) | (d as u16); + return (i + 2, true); + } + _ => {} + } + } + + let group = do p.read_atomically |p| { + if i == 0 || p.read_given_char(':').is_some() { + p.read_number(16, 4, 0x10000).map(|&n| n as u16) + } else { + None + } + }; + match group { + Some(g) => groups[i] = g, + None => return (i, false) + } + i += 1; + } + (i, false) + } + + let mut head = [0u16, ..8]; + let (head_size, head_ipv4) = read_groups(self, &mut head, 8); + + if head_size == 8 { + return Some(Ipv6Addr( + head[0], head[1], head[2], head[3], + head[4], head[5], head[6], head[7])) + } + + // IPv4 part is not allowed before `::` + if head_ipv4 { + return None + } + + // read `::` if previous code parsed less than 8 groups + if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() { + return None; + } + + let mut tail = [0u16, ..8]; + let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size); + Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size))) + } + + fn read_ipv6_addr(&mut self) -> Option { + do self.read_atomically |p| { + p.read_ipv6_addr_impl() + } + } + + fn read_ip_addr(&mut self) -> Option { + let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr(); + let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr(); + self.read_or([ipv4_addr, ipv6_addr]) + } + + fn read_socket_addr(&mut self) -> Option { + let ip_addr = |p: &mut Parser| { + let ipv4_p = |p: &mut Parser| p.read_ip_addr(); + let ipv6_p = |p: &mut Parser| { + let open_br = |p: &mut Parser| p.read_given_char('['); + let ip_addr = |p: &mut Parser| p.read_ipv6_addr(); + let clos_br = |p: &mut Parser| p.read_given_char(']'); + p.read_seq_3::(open_br, ip_addr, clos_br) + .map(|&t| match t { (_, ip, _) => ip }) + }; + p.read_or([ipv4_p, ipv6_p]) + }; + let colon = |p: &mut Parser| p.read_given_char(':'); + let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|&n| n as u16); + + // host, colon, port + self.read_seq_3::(ip_addr, colon, port) + .map(|&t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } }) + } +} + +impl FromStr for IpAddr { + fn from_str(s: &str) -> Option { + do Parser::new(s).read_till_eof |p| { + p.read_ip_addr() + } + } +} + +impl FromStr for SocketAddr { + fn from_str(s: &str) -> Option { + do Parser::new(s).read_till_eof |p| { + p.read_socket_addr() + } + } +} + + +#[cfg(test)] +mod test { + use super::*; + use from_str::FromStr; + use option::{Some, None}; + + #[test] + fn test_from_str_ipv4() { + assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1")); + assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255")); + assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0")); + + // out of range + assert_eq!(None, FromStr::from_str::("256.0.0.1")); + // too short + assert_eq!(None, FromStr::from_str::("255.0.0")); + // too long + assert_eq!(None, FromStr::from_str::("255.0.0.1.2")); + // no number between dots + assert_eq!(None, FromStr::from_str::("255.0..1")); + } + + #[test] + fn test_from_str_ipv6() { + assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0")); + assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1")); + + assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1")); + assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::")); + + assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), + FromStr::from_str("2a02:6b8::11:11")); + + // too long group + assert_eq!(None, FromStr::from_str::("::00000")); + // too short + assert_eq!(None, FromStr::from_str::("1:2:3:4:5:6:7")); + // too long + assert_eq!(None, FromStr::from_str::("1:2:3:4:5:6:7:8:9")); + // triple colon + assert_eq!(None, FromStr::from_str::("1:2:::6:7:8")); + // two double colons + assert_eq!(None, FromStr::from_str::("1:2::6::8")); + } + + #[test] + fn test_from_str_ipv4_in_ipv6() { + assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)), + FromStr::from_str("::192.0.2.33")); + assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), + FromStr::from_str("::FFFF:192.0.2.33")); + assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)), + FromStr::from_str("64:ff9b::192.0.2.33")); + assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)), + FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33")); + + // colon after v4 + assert_eq!(None, FromStr::from_str::("::127.0.0.1:")); + // not enought groups + assert_eq!(None, FromStr::from_str::("1.2.3.4.5:127.0.0.1")); + // too many groups + assert_eq!(None, FromStr::from_str::("1.2.3.4.5:6:7:127.0.0.1")); + } + + #[test] + fn test_from_str_socket_addr() { + assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }), + FromStr::from_str("77.88.21.11:80")); + assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }), + FromStr::from_str("[2a02:6b8:0:1::1]:53")); + assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }), + FromStr::from_str("[::127.0.0.1]:22")); + + // without port + assert_eq!(None, FromStr::from_str::("127.0.0.1")); + // without port + assert_eq!(None, FromStr::from_str::("127.0.0.1:")); + // wrong brackets around v4 + assert_eq!(None, FromStr::from_str::("[127.0.0.1]:22")); + // port out of range + assert_eq!(None, FromStr::from_str::("127.0.0.1:123456")); + } +} -- cgit 1.4.1-3-g733a5 From 58b11229e563da705e2579821b8c3fe1fa799c52 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 6 Aug 2013 13:35:13 +0400 Subject: Use FromStr for IpAddr in rt::uv::net --- src/libstd/rt/uv/net.rs | 72 ++----------------------------------------------- 1 file changed, 2 insertions(+), 70 deletions(-) (limited to 'src/libstd/rt') diff --git a/src/libstd/rt/uv/net.rs b/src/libstd/rt/uv/net.rs index fd3042899f6..c8b3d41a78d 100644 --- a/src/libstd/rt/uv/net.rs +++ b/src/libstd/rt/uv/net.rs @@ -20,7 +20,6 @@ use rt::uv::last_uv_error; use vec; use str; use from_str::{FromStr}; -use num; pub enum UvSocketAddr { UvIpv4SocketAddr(*sockaddr_in), @@ -85,77 +84,10 @@ fn uv_socket_addr_as_socket_addr(addr: UvSocketAddr, f: &fn(SocketAddr) -> T) port as u16 }; let ip_str = str::from_bytes_slice(ip_name).trim_right_chars(&'\x00'); - let ip = match addr { - UvIpv4SocketAddr(*) => { - let ip: ~[u8] = - ip_str.split_iter('.') - .transform(|s: &str| -> u8 { FromStr::from_str(s).unwrap() }) - .collect(); - assert_eq!(ip.len(), 4); - SocketAddr { - ip: Ipv4Addr(ip[0], ip[1], ip[2], ip[3]), - port: ip_port - } - }, - UvIpv6SocketAddr(*) => { - let ip: ~[u16] = { - let expand_shorthand_and_convert = |s: &str| -> ~[~[u16]] { - let convert_each_segment = |s: &str| -> ~[u16] { - let read_hex_segment = |s: &str| -> u16 { - num::FromStrRadix::from_str_radix(s, 16u).unwrap() - }; - match s { - "" => ~[], - // IPv4-Mapped/Compatible IPv6 Address? - s if s.find('.').is_some() => { - let i = s.rfind(':').unwrap_or_default(-1); - - let b = s.slice(i + 1, s.len()); // the ipv4 part - - let h = b.split_iter('.') - .transform(|s: &str| -> u8 { FromStr::from_str(s).unwrap() }) - .transform(|s: u8| -> ~str { fmt!("%02x", s as uint) }) - .collect::<~[~str]>(); - - if i == -1 { - // Ipv4 Compatible Address (::x.x.x.x) - // first 96 bits are zero leaving 32 bits - // for the ipv4 part - // (i.e ::127.0.0.1 == ::7F00:1) - ~[num::FromStrRadix::from_str_radix(h[0] + h[1], 16).unwrap(), - num::FromStrRadix::from_str_radix(h[2] + h[3], 16).unwrap()] - } else { - // Ipv4-Mapped Address (::FFFF:x.x.x.x) - // first 80 bits are zero, followed by all ones - // for the next 16 bits, leaving 32 bits for - // the ipv4 part - // (i.e ::FFFF:127.0.0.1 == ::FFFF:7F00:1) - ~[1, - num::FromStrRadix::from_str_radix(h[0] + h[1], 16).unwrap(), - num::FromStrRadix::from_str_radix(h[2] + h[3], 16).unwrap()] - } - }, - s => s.split_iter(':').transform(read_hex_segment).collect() - } - }; - s.split_str_iter("::").transform(convert_each_segment).collect() - }; - match expand_shorthand_and_convert(ip_str) { - [x] => x, // no shorthand found - [l, r] => l + vec::from_elem(8 - l.len() - r.len(), 0u16) + r, // fill the gap - _ => fail!(), // impossible. only one shorthand allowed. - } - }; - assert_eq!(ip.len(), 8); - SocketAddr { - ip: Ipv6Addr(ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]), - port: ip_port - } - }, - }; + let ip_addr = FromStr::from_str(ip_str).unwrap(); // finally run the closure - f(ip) + f(SocketAddr { ip: ip_addr, port: ip_port }) } pub fn uv_socket_addr_to_socket_addr(addr: UvSocketAddr) -> SocketAddr { -- cgit 1.4.1-3-g733a5 From d39255616004ea43dfabcf33b20ed2a80cd31dff Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 9 Aug 2013 01:15:31 -0700 Subject: std: Fix perf of local allocations in newsched Mostly optimizing TLS accesses to bring local heap allocation performance closer to that of oldsched. It's not completely at parity but removing the branches involved in supporting oldsched and optimizing pthread_get/setspecific to instead use our dedicated TCB slot will probably make up for it. --- src/libstd/os.rs | 4 ++-- src/libstd/rt/comm.rs | 4 ++-- src/libstd/rt/local_heap.rs | 22 ++++++++++++------- src/libstd/rt/mod.rs | 51 ++++++++++++++++++++++++++++----------------- src/libstd/sys.rs | 4 ++-- src/libstd/task/mod.rs | 15 ++++++------- src/libstd/task/spawn.rs | 17 +++++++-------- src/libstd/unstable/lang.rs | 17 +++++++-------- src/libstd/unstable/sync.rs | 26 ++++++++++++++--------- 9 files changed, 92 insertions(+), 68 deletions(-) (limited to 'src/libstd/rt') diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f246a61a4d5..f7bd2aa240d 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1142,9 +1142,9 @@ pub fn real_args() -> ~[~str] { #[cfg(target_os = "freebsd")] pub fn real_args() -> ~[~str] { use rt; - use rt::TaskContext; + use rt::NewRtContext; - if rt::context() == TaskContext { + if rt::context() == NewRtContext { match rt::args::clone() { Some(args) => args, None => fail!("process arguments not initialized") diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 936a6526508..793e244bec7 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -15,6 +15,7 @@ use cast; use ops::Drop; use rt::kill::BlockedTask; use kinds::Send; +use rt; use rt::sched::Scheduler; use rt::local::Local; use rt::select::{Select, SelectPort}; @@ -24,7 +25,6 @@ use util::Void; use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable}; use cell::Cell; use clone::Clone; -use rt::{context, SchedulerContext}; use tuple::ImmutableTuple; /// A combined refcount / BlockedTask-as-uint pointer. @@ -113,7 +113,7 @@ impl ChanOne { // 'do_resched' configures whether the scheduler immediately switches to // the receiving task, or leaves the sending task still running. fn try_send_inner(self, val: T, do_resched: bool) -> bool { - rtassert!(context() != SchedulerContext); + rtassert!(!rt::in_sched_context()); let mut this = self; let mut recvr_active = true; diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index e1e7ceacc38..8832597f40c 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -13,6 +13,7 @@ use libc; use libc::{c_void, uintptr_t, size_t}; use ops::Drop; +use option::{Some, None}; use rt; use rt::OldTaskContext; use rt::local::Local; @@ -86,8 +87,12 @@ impl Drop for LocalHeap { // A little compatibility function pub unsafe fn local_free(ptr: *libc::c_char) { - match rt::context() { - OldTaskContext => { + // XXX: Unsafe borrow for speed. Lame. + match Local::try_unsafe_borrow::() { + Some(task) => { + (*task).heap.free(ptr as *libc::c_void); + } + None => { rust_upcall_free_noswitch(ptr); extern { @@ -95,11 +100,6 @@ pub unsafe fn local_free(ptr: *libc::c_char) { fn rust_upcall_free_noswitch(ptr: *libc::c_char); } } - _ => { - do Local::borrow:: |task| { - task.heap.free(ptr as *libc::c_void); - } - } } } @@ -119,20 +119,28 @@ pub fn live_allocs() -> *raw::Box<()> { } extern { + #[fast_ffi] fn rust_new_memory_region(synchronized: uintptr_t, detailed_leaks: uintptr_t, poison_on_free: uintptr_t) -> *MemoryRegion; + #[fast_ffi] fn rust_delete_memory_region(region: *MemoryRegion); + #[fast_ffi] fn rust_new_boxed_region(region: *MemoryRegion, poison_on_free: uintptr_t) -> *BoxedRegion; + #[fast_ffi] fn rust_delete_boxed_region(region: *BoxedRegion); + #[fast_ffi] fn rust_boxed_region_malloc(region: *BoxedRegion, td: *TypeDesc, size: size_t) -> *OpaqueBox; + #[fast_ffi] fn rust_boxed_region_realloc(region: *BoxedRegion, ptr: *OpaqueBox, size: size_t) -> *OpaqueBox; + #[fast_ffi] fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox); + #[fast_ffi] fn rust_current_boxed_region() -> *BoxedRegion; } diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 01a52892f63..be71bc651df 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -407,14 +407,10 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int { /// or the old scheduler. #[deriving(Eq)] pub enum RuntimeContext { - // Only the exchange heap is available - GlobalContext, - // The scheduler may be accessed - SchedulerContext, - // Full task services, e.g. local heap, unwinding - TaskContext, // Running in an old-style task - OldTaskContext + OldTaskContext, + // Not old task context + NewRtContext } /// Determine the current RuntimeContext @@ -424,19 +420,8 @@ pub fn context() -> RuntimeContext { if unsafe { rust_try_get_task().is_not_null() } { return OldTaskContext; - } else if Local::exists::() { - // In this case we know it is a new runtime context, but we - // need to check which one. Going to try borrowing task to - // check. Task should always be in TLS, so hopefully this - // doesn't conflict with other ops that borrow. - return do Local::borrow:: |task| { - match task.task_type { - SchedTask => SchedulerContext, - GreenTask(_) => TaskContext - } - }; } else { - return GlobalContext; + return NewRtContext; } extern { @@ -444,3 +429,31 @@ pub fn context() -> RuntimeContext { pub fn rust_try_get_task() -> *rust_task; } } + +pub fn in_sched_context() -> bool { + unsafe { + match Local::try_unsafe_borrow::() { + Some(task) => { + match (*task).task_type { + SchedTask => true, + _ => false + } + } + None => false + } + } +} + +pub fn in_green_task_context() -> bool { + unsafe { + match Local::try_unsafe_borrow::() { + Some(task) => { + match (*task).task_type { + GreenTask(_) => true, + _ => false + } + } + None => false + } + } +} \ No newline at end of file diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index 9d853087123..15c096ad04f 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -136,7 +136,7 @@ impl FailWithCause for &'static str { pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { use either::Left; use option::{Some, None}; - use rt::{context, OldTaskContext, TaskContext}; + use rt::{context, OldTaskContext, in_green_task_context}; use rt::task::Task; use rt::local::Local; use rt::logging::Logger; @@ -158,7 +158,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { // XXX: Logging doesn't work correctly in non-task context because it // invokes the local heap - if context == TaskContext { + if in_green_task_context() { // XXX: Logging doesn't work here - the check to call the log // function never passes - so calling the log function directly. do Local::borrow:: |task| { diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index 2e0c9c1d1ad..269c828a984 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -42,7 +42,7 @@ use cmp::Eq; use comm::{stream, Chan, GenericChan, GenericPort, Port}; use result::Result; use result; -use rt::{context, OldTaskContext, TaskContext}; +use rt::{context, OldTaskContext, in_green_task_context}; use rt::local::Local; use unstable::finally::Finally; use util; @@ -527,14 +527,15 @@ pub fn try(f: ~fn() -> T) -> Result { pub fn with_task_name(blk: &fn(Option<&str>) -> U) -> U { use rt::task::Task; - match context() { - TaskContext => do Local::borrow:: |task| { + if in_green_task_context() { + do Local::borrow:: |task| { match task.name { Some(ref name) => blk(Some(name.as_slice())), None => blk(None) } - }, - _ => fail!("no task name exists in %?", context()), + } + } else { + fail!("no task name exists in %?", context()) } } @@ -614,7 +615,7 @@ pub fn unkillable(f: &fn() -> U) -> U { rt::rust_task_allow_kill(t); } } - TaskContext => { + _ if in_green_task_context() => { // The inhibits/allows might fail and need to borrow the task. let t = Local::unsafe_borrow::(); do (|| { @@ -645,7 +646,7 @@ pub unsafe fn rekillable(f: &fn() -> U) -> U { rt::rust_task_inhibit_kill(t); } } - TaskContext => { + _ if in_green_task_context() => { let t = Local::unsafe_borrow::(); do (|| { (*t).death.allow_kill((*t).unwinder.unwinding); diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 05a17f8539c..314377b8dc9 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -91,7 +91,7 @@ use to_bytes::IterBytes; use uint; use util; use unstable::sync::Exclusive; -use rt::{OldTaskContext, TaskContext, SchedulerContext, GlobalContext, context}; +use rt::{OldTaskContext, NewRtContext, context, in_green_task_context}; use rt::local::Local; use rt::task::{Task, Sched}; use rt::kill::KillHandle; @@ -526,7 +526,7 @@ impl RuntimeGlue { let me = rt::rust_get_task(); blk(OldTask(me), rt::rust_task_is_unwinding(me)) }, - TaskContext => unsafe { + NewRtContext if in_green_task_context() => unsafe { // Can't use safe borrow, because the taskgroup destructor needs to // access the scheduler again to send kill signals to other tasks. let me = Local::unsafe_borrow::(); @@ -535,7 +535,7 @@ impl RuntimeGlue { blk(NewTask((*me).death.kill_handle.get_ref().clone()), (*me).unwinder.unwinding) }, - SchedulerContext | GlobalContext => rtabort!("task dying in bad context"), + NewRtContext => rtabort!("task dying in bad context"), } } @@ -563,7 +563,7 @@ impl RuntimeGlue { } } }, - TaskContext => unsafe { + NewRtContext if in_green_task_context() => unsafe { // Can't use safe borrow, because creating new hashmaps for the // tasksets requires an rng, which needs to borrow the sched. let me = Local::unsafe_borrow::(); @@ -588,7 +588,7 @@ impl RuntimeGlue { Some(ref group) => group, }) }, - SchedulerContext | GlobalContext => rtabort!("spawning in bad context"), + NewRtContext => rtabort!("spawning in bad context"), } } } @@ -666,10 +666,9 @@ fn enlist_many(child: TaskHandle, child_arc: &TaskGroupArc, pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { match context() { - OldTaskContext => spawn_raw_oldsched(opts, f), - TaskContext => spawn_raw_newsched(opts, f), - SchedulerContext => fail!("can't spawn from scheduler context"), - GlobalContext => fail!("can't spawn from global context"), + OldTaskContext => spawn_raw_oldsched(opts, f), + _ if in_green_task_context() => spawn_raw_newsched(opts, f), + _ => fail!("can't spawn from this context") } } diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index 98c0fe254b6..c5112529aed 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -12,9 +12,9 @@ use cast::transmute; use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int}; +use option::{Some, None}; use str; use sys; -use rt::{context, OldTaskContext}; use rt::task::Task; use rt::local::Local; use rt::borrowck; @@ -56,16 +56,13 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, #[lang="malloc"] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { - match context() { - OldTaskContext => { - return rustrt::rust_upcall_malloc_noswitch(td, size); + // XXX: Unsafe borrow for speed. Lame. + match Local::try_unsafe_borrow::() { + Some(task) => { + (*task).heap.alloc(td as *c_void, size as uint) as *c_char } - _ => { - let mut alloc = ::ptr::null(); - do Local::borrow:: |task| { - alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char; - } - return alloc; + None => { + rustrt::rust_upcall_malloc_noswitch(td, size) } } } diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 225ac5c92ad..a8d942a46b3 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -282,7 +282,7 @@ pub unsafe fn atomically(f: &fn() -> U) -> U { use rt::task::Task; use task::rt; use rt::local::Local; - use rt::{context, OldTaskContext, TaskContext}; + use rt::{context, OldTaskContext}; match context() { OldTaskContext => { @@ -296,17 +296,23 @@ pub unsafe fn atomically(f: &fn() -> U) -> U { rt::rust_task_allow_kill(t); } } - TaskContext => { - let t = Local::unsafe_borrow::(); - do (|| { - (*t).death.inhibit_yield(); - f() - }).finally { - (*t).death.allow_yield(); + _ => { + let t = Local::try_unsafe_borrow::(); + match t { + Some(t) => { + do (|| { + (*t).death.inhibit_yield(); + f() + }).finally { + (*t).death.allow_yield(); + } + } + None => { + // FIXME(#3095): As in unkillable(). + f() + } } } - // FIXME(#3095): As in unkillable(). - _ => f() } } -- cgit 1.4.1-3-g733a5 From ae81151ad63e2db7ec893f90a4e99592cabb6b30 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Fri, 9 Aug 2013 13:53:28 +0400 Subject: Fix Ipv6Addr to_str for ::1:x.x.x.x addresses Reported by luqmana@ --- src/libstd/rt/io/net/ip.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/libstd/rt') diff --git a/src/libstd/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs index 81269d197d5..77176088801 100644 --- a/src/libstd/rt/io/net/ip.rs +++ b/src/libstd/rt/io/net/ip.rs @@ -43,7 +43,7 @@ impl ToStr for IpAddr { } // Ipv4-Mapped address - Ipv6Addr(0, 0, 0, 0, 0, 1, g, h) => { + Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => { let a = fmt!("%04x", g as uint); let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap(); let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap(); @@ -437,4 +437,11 @@ mod test { // port out of range assert_eq!(None, FromStr::from_str::("127.0.0.1:123456")); } + + #[test] + fn ipv6_addr_to_str() { + let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280); + assert!(a1.to_str() == ~"::ffff:192.0.2.128" || a1.to_str() == ~"::FFFF:192.0.2.128"); + } + } -- cgit 1.4.1-3-g733a5