From 24d3979ce871dba7f20168dd0aebe5abd69644e7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Jul 2014 10:50:25 +1000 Subject: [PATCH] Add a `task_info` crate and a `task_basic_info` module within it. The crate provides an interface to the Mac-specific `task_info()` function in general, and the module provides an interface to the TASK_BASIC_INFO flavor. Currently only the `virtual_size` and `resident_size` values of the `task_basic_info` struct are exposed, but there's obvious room for expansion. This is used to implement the -m measurements on Mac. --- Makefile.in | 2 + configure | 1 + src/README.md | 1 + src/components/util/memory.rs | 38 ++++++++----- src/components/util/util.rs | 2 + src/platform/macos/rust-task_info/Makefile.in | 32 +++++++++++ src/platform/macos/rust-task_info/configure | 4 ++ .../macos/rust-task_info/task_basic_info.rs | 55 +++++++++++++++++++ src/platform/macos/rust-task_info/task_info.c | 39 +++++++++++++ .../macos/rust-task_info/task_info.rc | 23 ++++++++ 10 files changed, 184 insertions(+), 13 deletions(-) create mode 100644 src/platform/macos/rust-task_info/Makefile.in create mode 100755 src/platform/macos/rust-task_info/configure create mode 100644 src/platform/macos/rust-task_info/task_basic_info.rs create mode 100644 src/platform/macos/rust-task_info/task_info.c create mode 100644 src/platform/macos/rust-task_info/task_info.rc diff --git a/Makefile.in b/Makefile.in index dcc55e264e1..c2a2537a07b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -390,10 +390,12 @@ ifeq ($(CFG_OSTYPE),apple-darwin) package: servo mkdir -p Servo.app/Contents/MacOS/src/platform/macos/rust-cocoa + mkdir -p Servo.app/Contents/MacOS/src/platform/macos/rust-task_info mkdir -p Servo.app/Contents/MacOS/src/support/azure/rust-azure cp $(S)Info.plist Servo.app/Contents/ cp servo Servo.app/Contents/MacOS/ cp $(B)src/platform/macos/rust-cocoa/lib*.dylib Servo.app/Contents/MacOS/src/platform/macos/rust-cocoa/ + cp $(B)src/platform/macos/rust-task_info/lib*.dylib Servo.app/Contents/MacOS/src/platform/macos/rust-task_info/ cp $(B)src/support/azure/rust-azure/lib*.dylib Servo.app/Contents/MacOS/src/support/azure/rust-azure/ else ifeq ($(CFG_OSTYPE),linux-androideabi) diff --git a/configure b/configure index 14d0fe8791c..cd29315fbdc 100755 --- a/configure +++ b/configure @@ -534,6 +534,7 @@ CFG_SUBMODULES="\ support/glfw/glfw \ support/glfw/glfw-rs \ platform/macos/rust-cocoa \ + platform/macos/rust-task_info \ ${CFG_SUBMODULES}" fi diff --git a/src/README.md b/src/README.md index 5efad09e8dc..42b336e2401 100644 --- a/src/README.md +++ b/src/README.md @@ -54,6 +54,7 @@ they are designed to be useful in other Rust projects. * `platform/macos/rust-core-graphics`: Bindings to Core Graphics/Quartz. * `platform/macos/rust-core-text`: Bindings to Core Text. * `platform/macos/rust-io-surface`: Bindings to the `IOSurface` library. +* `platform/macos/rust-task_info`: Bindings to `task_info()`. ## Tests diff --git a/src/components/util/memory.rs b/src/components/util/memory.rs index 24414fad945..c3d1d6e10de 100644 --- a/src/components/util/memory.rs +++ b/src/components/util/memory.rs @@ -10,6 +10,8 @@ use std::io::File; #[cfg(target_os="linux")] use std::os::page_size; use task::spawn_named; +#[cfg(target_os="macos")] +use task_info::task_basic_info::{virtual_size,resident_size}; pub struct MemoryProfilerChan(pub Sender); @@ -98,7 +100,7 @@ impl MemoryProfiler { } } - fn print_measurement(path: &str, nbytes: Option) { + fn print_measurement(path: &str, nbytes: Option) { match nbytes { Some(nbytes) => { let mebi = 1024f64 * 1024f64; @@ -124,35 +126,45 @@ macro_rules! option_try( ) #[cfg(target_os="linux")] -fn get_proc_self_statm_field(field: uint) -> Option { +fn get_proc_self_statm_field(field: uint) -> Option { let mut f = File::open(&Path::new("/proc/self/statm")); match f.read_to_str() { Ok(contents) => { let s = option_try!(contents.as_slice().words().nth(field)); - let npages: i64 = option_try!(from_str(s)); - Some(npages * (page_size() as i64)) + let npages: u64 = option_try!(from_str(s)); + Some(npages * (page_size() as u64)) } Err(_) => None } } #[cfg(target_os="linux")] -fn get_vsize() -> Option { +fn get_vsize() -> Option { get_proc_self_statm_field(0) } -#[cfg(not(target_os="linux"))] -fn get_vsize() -> Option { - None -} - #[cfg(target_os="linux")] -fn get_resident() -> Option { +fn get_resident() -> Option { get_proc_self_statm_field(1) } -#[cfg(not(target_os="linux"))] -fn get_resident() -> Option { +#[cfg(target_os="macos")] +fn get_vsize() -> Option { + virtual_size() +} + +#[cfg(target_os="macos")] +fn get_resident() -> Option { + resident_size() +} + +#[cfg(not(target_os="linux"), not(target_os = "macos"))] +fn get_vsize() -> Option { + None +} + +#[cfg(not(target_os="linux"), not(target_os = "macos"))] +fn get_resident() -> Option { None } diff --git a/src/components/util/util.rs b/src/components/util/util.rs index 2e206b1fe8e..31f0b2295c9 100644 --- a/src/components/util/util.rs +++ b/src/components/util/util.rs @@ -24,6 +24,8 @@ extern crate rand; extern crate rustrt; extern crate serialize; extern crate sync; +#[cfg(target_os="macos")] +extern crate task_info; extern crate std_time = "time"; extern crate std_url = "url"; diff --git a/src/platform/macos/rust-task_info/Makefile.in b/src/platform/macos/rust-task_info/Makefile.in new file mode 100644 index 00000000000..193196d6f7d --- /dev/null +++ b/src/platform/macos/rust-task_info/Makefile.in @@ -0,0 +1,32 @@ +VPATH=%VPATH% + +CC=gcc +RUSTC ?= rustc +AR ?= ar +RUSTFLAGS ?= +CFLAGS=-Wall + +RUST_SRC = $(shell find $(VPATH)/. -type f -name '*.rs') + +.PHONY: all +all: libtask_info.dummy + +libtask_info.dummy: task_info.rc $(RUST_SRC) libtask_info.a + $(RUSTC) $(RUSTFLAGS) $< --out-dir . + touch $@ + +task_info-test: task_info.rc $(RUST_SRC) libtask_info.a + $(RUSTC) $(RUSTFLAGS) $< -o $@ --test + +libtask_info.a: task_info.o + $(AR) rcs libtask_info.a task_info.o + +task_info.o: task_info.c + $(CC) $(CFLAGS) $< -o $@ -c + +check: task_info-test + ./task_info-test + +.PHONY: clean +clean: + rm -f task_info-test *.a *.o *.so *.dylib *.rlib *.dll *.dummy task_info-test diff --git a/src/platform/macos/rust-task_info/configure b/src/platform/macos/rust-task_info/configure new file mode 100755 index 00000000000..62a0f4cd3e6 --- /dev/null +++ b/src/platform/macos/rust-task_info/configure @@ -0,0 +1,4 @@ +#!/bin/bash + +SRCDIR="$(cd $(dirname $0) && pwd)" +sed "s#%VPATH%#${SRCDIR}#" ${SRCDIR}/Makefile.in > Makefile diff --git a/src/platform/macos/rust-task_info/task_basic_info.rs b/src/platform/macos/rust-task_info/task_basic_info.rs new file mode 100644 index 00000000000..9d87ac7bc20 --- /dev/null +++ b/src/platform/macos/rust-task_info/task_basic_info.rs @@ -0,0 +1,55 @@ +// Copyright 2014 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Interface to the measurements in the task_basic_info struct, gathered by +//! invoking `task_info()` with the `TASK_BASIC_INFO` flavor. + +use libc::{c_int,uint64_t}; + +/// Obtains task_basic_info::virtual_size. +pub fn virtual_size() -> Option { + let mut virtual_size: u64 = 0; + let mut rv; + unsafe { + rv = TaskBasicInfoVirtualSize(&mut virtual_size); + } + if rv == 0 { Some(virtual_size) } else { None } +} + +/// Obtains task_basic_info::resident_size. +pub fn resident_size() -> Option { + let mut resident_size: u64 = 0; + let mut rv; + unsafe { + rv = TaskBasicInfoResidentSize(&mut resident_size); + } + if rv == 0 { Some(resident_size) } else { None } +} + +#[link(name = "task_info")] +extern { + fn TaskBasicInfoVirtualSize(virtual_size: *mut uint64_t) -> c_int; + fn TaskBasicInfoResidentSize(resident_size: *mut uint64_t) -> c_int; +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_stuff() { + // In theory these can fail to return a value, but in practice they + // don't unless something really bizarre has happened with the OS. So + // assume they succeed. The returned values are non-deterministic, but + // check they're non-zero as a basic sanity test. + assert!(virtual_size().unwrap() > 0); + assert!(resident_size().unwrap() > 0); + } +} + diff --git a/src/platform/macos/rust-task_info/task_info.c b/src/platform/macos/rust-task_info/task_info.c new file mode 100644 index 00000000000..e8f59082609 --- /dev/null +++ b/src/platform/macos/rust-task_info/task_info.c @@ -0,0 +1,39 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include + +static int +TaskBasicInfo(struct task_basic_info* info) +{ + mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; + kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO, + (task_info_t)info, &count); + return kr == KERN_SUCCESS ? 0 : -1; +} + +int +TaskBasicInfoVirtualSize(int64_t *virtualSize) +{ + struct task_basic_info ti; + int rv = TaskBasicInfo(&ti); + *virtualSize = (rv == 0) ? ti.virtual_size : 0; + return rv; +} + +int +TaskBasicInfoResidentSize(int64_t *residentSize) +{ + struct task_basic_info ti; + int rv = TaskBasicInfo(&ti); + *residentSize = (rv == 0) ? ti.resident_size : 0; + return rv; +} + diff --git a/src/platform/macos/rust-task_info/task_info.rc b/src/platform/macos/rust-task_info/task_info.rc new file mode 100644 index 00000000000..b7814a48b5f --- /dev/null +++ b/src/platform/macos/rust-task_info/task_info.rc @@ -0,0 +1,23 @@ +// Copyright 2014 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_id = "github.com/mozilla-servo/rust-task_info#task_info:0.1"] +#![crate_type = "lib"] +#![crate_type = "dylib"] +#![crate_type = "rlib"] + +#![comment = "The Servo Parallel Browser Project"] +#![license = "MPL"] + +#![feature(globs)] + +extern crate libc; + +pub mod task_basic_info; +