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.
This commit is contained in:
Nicholas Nethercote 2014-07-08 10:50:25 +10:00
parent f8fbf557f1
commit 24d3979ce8
10 changed files with 184 additions and 13 deletions

View file

@ -390,10 +390,12 @@ ifeq ($(CFG_OSTYPE),apple-darwin)
package: servo package: servo
mkdir -p Servo.app/Contents/MacOS/src/platform/macos/rust-cocoa 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 mkdir -p Servo.app/Contents/MacOS/src/support/azure/rust-azure
cp $(S)Info.plist Servo.app/Contents/ cp $(S)Info.plist Servo.app/Contents/
cp servo Servo.app/Contents/MacOS/ 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-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/ cp $(B)src/support/azure/rust-azure/lib*.dylib Servo.app/Contents/MacOS/src/support/azure/rust-azure/
else ifeq ($(CFG_OSTYPE),linux-androideabi) else ifeq ($(CFG_OSTYPE),linux-androideabi)

1
configure vendored
View file

@ -534,6 +534,7 @@ CFG_SUBMODULES="\
support/glfw/glfw \ support/glfw/glfw \
support/glfw/glfw-rs \ support/glfw/glfw-rs \
platform/macos/rust-cocoa \ platform/macos/rust-cocoa \
platform/macos/rust-task_info \
${CFG_SUBMODULES}" ${CFG_SUBMODULES}"
fi fi

View file

@ -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-graphics`: Bindings to Core Graphics/Quartz.
* `platform/macos/rust-core-text`: Bindings to Core Text. * `platform/macos/rust-core-text`: Bindings to Core Text.
* `platform/macos/rust-io-surface`: Bindings to the `IOSurface` library. * `platform/macos/rust-io-surface`: Bindings to the `IOSurface` library.
* `platform/macos/rust-task_info`: Bindings to `task_info()`.
## Tests ## Tests

View file

@ -10,6 +10,8 @@ use std::io::File;
#[cfg(target_os="linux")] #[cfg(target_os="linux")]
use std::os::page_size; use std::os::page_size;
use task::spawn_named; use task::spawn_named;
#[cfg(target_os="macos")]
use task_info::task_basic_info::{virtual_size,resident_size};
pub struct MemoryProfilerChan(pub Sender<MemoryProfilerMsg>); pub struct MemoryProfilerChan(pub Sender<MemoryProfilerMsg>);
@ -98,7 +100,7 @@ impl MemoryProfiler {
} }
} }
fn print_measurement(path: &str, nbytes: Option<i64>) { fn print_measurement(path: &str, nbytes: Option<u64>) {
match nbytes { match nbytes {
Some(nbytes) => { Some(nbytes) => {
let mebi = 1024f64 * 1024f64; let mebi = 1024f64 * 1024f64;
@ -124,35 +126,45 @@ macro_rules! option_try(
) )
#[cfg(target_os="linux")] #[cfg(target_os="linux")]
fn get_proc_self_statm_field(field: uint) -> Option<i64> { fn get_proc_self_statm_field(field: uint) -> Option<u64> {
let mut f = File::open(&Path::new("/proc/self/statm")); let mut f = File::open(&Path::new("/proc/self/statm"));
match f.read_to_str() { match f.read_to_str() {
Ok(contents) => { Ok(contents) => {
let s = option_try!(contents.as_slice().words().nth(field)); let s = option_try!(contents.as_slice().words().nth(field));
let npages: i64 = option_try!(from_str(s)); let npages: u64 = option_try!(from_str(s));
Some(npages * (page_size() as i64)) Some(npages * (page_size() as u64))
} }
Err(_) => None Err(_) => None
} }
} }
#[cfg(target_os="linux")] #[cfg(target_os="linux")]
fn get_vsize() -> Option<i64> { fn get_vsize() -> Option<u64> {
get_proc_self_statm_field(0) get_proc_self_statm_field(0)
} }
#[cfg(not(target_os="linux"))]
fn get_vsize() -> Option<i64> {
None
}
#[cfg(target_os="linux")] #[cfg(target_os="linux")]
fn get_resident() -> Option<i64> { fn get_resident() -> Option<u64> {
get_proc_self_statm_field(1) get_proc_self_statm_field(1)
} }
#[cfg(not(target_os="linux"))] #[cfg(target_os="macos")]
fn get_resident() -> Option<i64> { fn get_vsize() -> Option<u64> {
virtual_size()
}
#[cfg(target_os="macos")]
fn get_resident() -> Option<u64> {
resident_size()
}
#[cfg(not(target_os="linux"), not(target_os = "macos"))]
fn get_vsize() -> Option<u64> {
None
}
#[cfg(not(target_os="linux"), not(target_os = "macos"))]
fn get_resident() -> Option<u64> {
None None
} }

View file

@ -24,6 +24,8 @@ extern crate rand;
extern crate rustrt; extern crate rustrt;
extern crate serialize; extern crate serialize;
extern crate sync; extern crate sync;
#[cfg(target_os="macos")]
extern crate task_info;
extern crate std_time = "time"; extern crate std_time = "time";
extern crate std_url = "url"; extern crate std_url = "url";

View file

@ -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

4
src/platform/macos/rust-task_info/configure vendored Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
SRCDIR="$(cd $(dirname $0) && pwd)"
sed "s#%VPATH%#${SRCDIR}#" ${SRCDIR}/Makefile.in > Makefile

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<u64> {
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<u64> {
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);
}
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#include <mach/mach_init.h>
#include <mach/task.h>
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;
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;