├── .gitignore ├── .rustfmt.toml ├── .travis.yml ├── Cargo.toml ├── README.md ├── Xargo.std.toml ├── Xargo.test.toml ├── Xargo.toml ├── build-docker-image.sh ├── ci ├── after_success.sh ├── install.sh └── script.sh ├── docker ├── aarch64-unknown-linux-steed.json ├── aarch64-unknown-linux-steed │ └── Dockerfile ├── arm-unknown-linux-steedeabi.json ├── arm-unknown-linux-steedeabi │ └── Dockerfile ├── arm-unknown-linux-steedeabihf.json ├── arm-unknown-linux-steedeabihf │ └── Dockerfile ├── armv7-unknown-linux-steedeabihf.json ├── armv7-unknown-linux-steedeabihf │ └── Dockerfile ├── i686-unknown-linux-steed.json ├── i686-unknown-linux-steed │ └── Dockerfile ├── lld.sh ├── mips-unknown-linux-steed.json ├── mips-unknown-linux-steed │ └── Dockerfile ├── mipsel-unknown-linux-steed.json ├── mipsel-unknown-linux-steed │ └── Dockerfile ├── powerpc-unknown-linux-steed.json ├── powerpc-unknown-linux-steed │ └── Dockerfile ├── powerpc64-unknown-linux-steed.json ├── powerpc64-unknown-linux-steed │ └── Dockerfile ├── powerpc64le-unknown-linux-steed.json ├── powerpc64le-unknown-linux-steed │ └── Dockerfile ├── qemu.sh ├── x86_64-unknown-linux-steed.json ├── x86_64-unknown-linux-steed │ └── Dockerfile └── xargo.sh ├── examples ├── _llseek.rs ├── args.rs ├── canonicalize.rs ├── chdir.rs ├── create.rs ├── dup.rs ├── echo.rs ├── env.rs ├── execve.rs ├── format.rs ├── hashmap.rs ├── hello.rs ├── instant.rs ├── ls.rs ├── mutex.rs ├── one.rs ├── open.rs ├── panic.rs ├── preadwrite.rs ├── print.rs ├── stat.rs ├── stderr.rs ├── system-time.rs ├── tcp_listen_connect.rs ├── thread.rs ├── vec.rs └── zero.rs ├── generate └── errno.py ├── naive_ralloc ├── Cargo.toml └── src │ └── lib.rs ├── src ├── ascii.rs ├── collections │ ├── hash │ │ ├── bench.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── set.rs │ │ └── table.rs │ └── mod.rs ├── ctypes.rs ├── env.rs ├── error.rs ├── ffi │ ├── c_str.rs │ ├── mod.rs │ └── os_str.rs ├── fs.rs ├── io │ ├── buffered.rs │ ├── cursor.rs │ ├── error.rs │ ├── impls.rs │ ├── lazy.rs │ ├── mod.rs │ ├── prelude.rs │ ├── stdio.rs │ └── util.rs ├── lib.rs ├── libc │ ├── internal │ │ ├── aarch64.rs │ │ ├── arm.rs │ │ ├── mips.rs │ │ ├── mips64.rs │ │ ├── mod.rs │ │ ├── powerpc.rs │ │ ├── powerpc64.rs │ │ ├── sparc64.rs │ │ ├── x86.rs │ │ └── x86_64.rs │ └── mod.rs ├── linux │ ├── aarch64.rs │ ├── arm.rs │ ├── errno.rs │ ├── mips.rs │ ├── mips64.rs │ ├── mod.rs │ ├── powerpc.rs │ ├── powerpc64.rs │ ├── sparc64.rs │ ├── types.rs │ ├── x86.rs │ └── x86_64.rs ├── macros.rs ├── memchr.rs ├── net │ ├── addr.rs │ ├── ip.rs │ ├── mod.rs │ ├── parser.rs │ ├── tcp.rs │ ├── test.rs │ └── udp.rs ├── num.rs ├── os │ ├── linux │ │ ├── fs.rs │ │ ├── mod.rs │ │ └── raw.rs │ ├── mod.rs │ └── raw.rs ├── panicking.rs ├── path.rs ├── prelude │ ├── mod.rs │ └── v1.rs ├── process.rs ├── rand │ ├── mod.rs │ └── reader.rs ├── rt.rs ├── sync │ ├── mod.rs │ └── mutex.rs ├── sys │ ├── linux │ │ ├── args.rs │ │ ├── env.rs │ │ ├── ext │ │ │ ├── ffi.rs │ │ │ ├── fs.rs │ │ │ ├── io.rs │ │ │ ├── mod.rs │ │ │ └── net.rs │ │ ├── fd.rs │ │ ├── fs.rs │ │ ├── memchr.rs │ │ ├── mod.rs │ │ ├── mutex.rs │ │ ├── net.rs │ │ ├── os.rs │ │ ├── os_str.rs │ │ ├── parking_lot │ │ │ ├── LICENSE-APACHE │ │ │ ├── LICENSE-MIT │ │ │ ├── core │ │ │ │ ├── mod.rs │ │ │ │ ├── parking_lot.rs │ │ │ │ ├── spinwait.rs │ │ │ │ ├── thread_parker │ │ │ │ │ └── linux.rs │ │ │ │ ├── util.rs │ │ │ │ └── word_lock.rs │ │ │ ├── mod.rs │ │ │ └── raw_mutex.rs │ │ ├── path.rs │ │ ├── pipe.rs │ │ ├── process.rs │ │ ├── rand.rs │ │ ├── stack_overflow.rs │ │ ├── thread.rs │ │ └── time.rs │ └── mod.rs ├── sys_common │ ├── io.rs │ ├── mod.rs │ ├── mutex.rs │ ├── net.rs │ ├── poison.rs │ ├── thread.rs │ └── util.rs ├── thread │ └── mod.rs └── time │ ├── duration.rs │ └── mod.rs └── test ├── Cargo.toml └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | *.rs.bk 2 | Cargo.lock 3 | target 4 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: rust 3 | services: docker 4 | sudo: required 5 | 6 | matrix: 7 | include: 8 | # Tier 1 9 | - env: TARGET=x86_64-unknown-linux-steed 10 | rust: nightly 11 | - env: TARGET=aarch64-unknown-linux-steed 12 | rust: nightly 13 | - env: TARGET=arm-unknown-linux-steedeabi 14 | rust: nightly 15 | - env: TARGET=arm-unknown-linux-steedeabihf 16 | rust: nightly 17 | - env: TARGET=armv7-unknown-linux-steedeabihf 18 | rust: nightly 19 | - env: TARGET=i686-unknown-linux-steed 20 | rust: nightly 21 | 22 | # Tier 2 23 | - env: TARGET=mips-unknown-linux-steed 24 | rust: nightly 25 | # - env: TARGET=mips64-unknown-linux-steedabi64 26 | # rust: nightly 27 | # - env: TARGET=mips64el-unknown-linux-steedabi64 28 | # rust: nightly 29 | - env: TARGET=mipsel-unknown-linux-steed 30 | rust: nightly 31 | - env: TARGET=powerpc64-unknown-linux-steed 32 | rust: nightly 33 | # - env: TARGET=powerpc64le-unknown-linux-steed 34 | # rust: nightly 35 | # - env: TARGET=s390x-unknown-linux-steed 36 | # rust: nightly 37 | # - env: TARGET=sparc64-unknown-linux-steed 38 | # rust: nightly 39 | 40 | allow_failures: 41 | - env: TARGET=powerpc-unknown-linux-steed 42 | 43 | install: 44 | - set -e 45 | - bash ci/install.sh 46 | - source ~/.cargo/env 47 | 48 | script: 49 | - bash ci/script.sh 50 | 51 | after_success: 52 | - bash ci/after_success.sh 53 | 54 | after_script: set +e 55 | 56 | before_cache: 57 | - docker history -q japaric/$TARGET:v0.1.12 | 58 | grep -v \ | 59 | xargs docker save | 60 | gzip > $HOME/docker/$TARGET.tar.gz 61 | 62 | cache: 63 | directories: 64 | - $HOME/.cargo 65 | - $HOME/.xargo 66 | - $HOME/docker 67 | - $TRAVIS_BUILD_DIR/target 68 | 69 | before_install: 70 | - zcat $HOME/docker/$TARGET.tar.gz | docker load || true 71 | 72 | branches: 73 | only: 74 | - auto 75 | - master 76 | - try 77 | 78 | notifications: 79 | email: 80 | on_success: never 81 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | # This is NOT an official Rust project but since most code will come from 3 | # the rust-lang/rust repo it makes sense to use this author. 4 | authors = ["The Rust Project Developers"] 5 | name = "std" 6 | version = "0.1.0" 7 | 8 | [dependencies] 9 | sc = "0.2.1" 10 | 11 | [dependencies.ralloc] 12 | default-features = false 13 | features = ["allocator"] 14 | git = "https://github.com/redox-os/ralloc" 15 | optional = true 16 | 17 | [dependencies.naive_ralloc] 18 | optional = true 19 | path = "naive_ralloc" 20 | 21 | [features] 22 | default = ["ralloc"] 23 | 24 | [profile.release] 25 | lto = true 26 | -------------------------------------------------------------------------------- /Xargo.std.toml: -------------------------------------------------------------------------------- 1 | [dependencies] 2 | collections = {} 3 | rand = {} 4 | 5 | [dependencies.compiler_builtins] 6 | features = ["mem"] 7 | git = "https://github.com/rust-lang-nursery/compiler-builtins" 8 | stage = 1 9 | 10 | [dependencies.std] 11 | git = "https://github.com/japaric/steed" 12 | stage = 2 -------------------------------------------------------------------------------- /Xargo.test.toml: -------------------------------------------------------------------------------- 1 | [dependencies] 2 | collections = {} 3 | rand = {} 4 | 5 | [dependencies.compiler_builtins] 6 | features = ["mem"] 7 | git = "https://github.com/rust-lang-nursery/compiler-builtins" 8 | stage = 1 9 | 10 | [dependencies.std] 11 | git = "https://github.com/japaric/steed" 12 | stage = 2 13 | 14 | [dependencies.test] 15 | git = "https://github.com/japaric/steed" 16 | stage = 3 -------------------------------------------------------------------------------- /Xargo.toml: -------------------------------------------------------------------------------- 1 | [dependencies] 2 | collections = {} 3 | rand = {} 4 | 5 | [dependencies.compiler_builtins] 6 | features = ["mem"] 7 | stage = 1 8 | -------------------------------------------------------------------------------- /build-docker-image.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | run() { 4 | local tag=$(cross -V | head -n1 | cut -d' ' -f2) 5 | docker build \ 6 | -t japaric/${1}:v$tag \ 7 | -f docker/${1}/Dockerfile \ 8 | docker 9 | } 10 | 11 | if [ -z $1 ]; then 12 | for t in `ls docker/`; do 13 | if [ -d docker/$t ]; then 14 | run $t 15 | fi 16 | done 17 | else 18 | run $1 19 | fi 20 | -------------------------------------------------------------------------------- /ci/after_success.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | main() { 4 | set +x 5 | docker login \ 6 | -p "$DOCKER_PASS" \ 7 | -u "$DOCKER_USER" 8 | set -x 9 | 10 | docker push japaric/$TARGET 11 | 12 | if [ $TARGET = x86_64-unknown-linux-gnu ]; then 13 | cargo doc --target $TARGET 14 | 15 | mkdir ghp-import 16 | 17 | curl -Ls https://github.com/davisp/ghp-import/archive/master.tar.gz | \ 18 | tar --strip-components 1 -C ghp-import -xz 19 | 20 | ./ghp-import/ghp_import.py target/$TARGET/doc 21 | 22 | set +x 23 | git push -fq https://$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git gh-pages && \ 24 | echo OK 25 | fi 26 | } 27 | 28 | if [ $TRAVIS_BRANCH = master ]; then 29 | main 30 | fi 31 | -------------------------------------------------------------------------------- /ci/install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | main() { 4 | # This fetches latest stable release 5 | local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \ 6 | | cut -d/ -f3 \ 7 | | grep -E '^v[0.1.0-9.]+$' \ 8 | | sort --version-sort \ 9 | | tail -n1) 10 | 11 | curl -LSfs https://japaric.github.io/trust/install.sh | \ 12 | sh -s -- \ 13 | --force \ 14 | --git japaric/cross \ 15 | --tag $tag \ 16 | --target x86_64-unknown-linux-musl 17 | } 18 | 19 | main 20 | -------------------------------------------------------------------------------- /ci/script.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | main() { 4 | sh build-docker-image.sh $TARGET 5 | 6 | if [ $TRAVIS_BRANCH = master ]; then 7 | return 8 | fi 9 | 10 | local examples=( 11 | _llseek 12 | args 13 | chdir 14 | create 15 | dup 16 | env 17 | format 18 | hashmap 19 | hello 20 | instant 21 | ls 22 | open 23 | preadwrite 24 | stat 25 | stderr 26 | system-time 27 | tcp_listen_connect 28 | thread 29 | vec 30 | zero 31 | ) 32 | 33 | for example in ${examples[@]}; do 34 | cross run \ 35 | --target $TARGET \ 36 | --no-default-features \ 37 | --features naive_ralloc \ 38 | --example $example 39 | done 40 | 41 | for example in ${examples[@]}; do 42 | cross run \ 43 | --target $TARGET \ 44 | --no-default-features \ 45 | --features naive_ralloc \ 46 | --example $example --release 47 | done 48 | 49 | cat >>Xargo.toml <<'EOF' 50 | 51 | [dependencies.std] 52 | default-features = false 53 | features = ["naive_ralloc"] 54 | path = "/project" 55 | stage = 2 56 | 57 | [dependencies.test] 58 | path = "/project/test" 59 | stage = 3 60 | EOF 61 | 62 | cross test \ 63 | --target $TARGET \ 64 | --no-default-features \ 65 | --features naive_ralloc 66 | 67 | set +x 68 | pushd target/$TARGET/release/examples 69 | size ${examples[@]} 70 | popd 71 | } 72 | 73 | main 74 | -------------------------------------------------------------------------------- /docker/aarch64-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi-blacklist": [ 3 | "stdcall", 4 | "fastcall", 5 | "vectorcall", 6 | "win64", 7 | "sysv64" 8 | ], 9 | "arch": "aarch64", 10 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 11 | "env": "steed", 12 | "executables": true, 13 | "has-elf-tls": true, 14 | "linker": "ld.lld", 15 | "linker-flavor": "ld", 16 | "llvm-target": "aarch64-unknown-linux", 17 | "max-atomic-width": 128, 18 | "os": "linux", 19 | "panic-strategy": "abort", 20 | "pre-link-args": { 21 | "gcc": [ 22 | "-Wl,--as-needed", 23 | "-Wl,-z,noexecstack", 24 | "-nostartfiles" 25 | ] 26 | }, 27 | "target-c-int-width": "32", 28 | "target-endian": "little", 29 | "target-family": "unix", 30 | "target-pointer-width": "64", 31 | "vendor": "unknown" 32 | } 33 | -------------------------------------------------------------------------------- /docker/aarch64-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY qemu.sh / 17 | RUN bash /qemu.sh 2.10.1 aarch64 18 | 19 | COPY aarch64-unknown-linux-steed.json /json 20 | 21 | ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_STEED_RUNNER=qemu-aarch64 \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/arm-unknown-linux-steedeabi.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi-blacklist": [ 3 | "stdcall", 4 | "fastcall", 5 | "vectorcall", 6 | "win64", 7 | "sysv64" 8 | ], 9 | "arch": "arm", 10 | "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", 11 | "env": "steed", 12 | "executables": true, 13 | "features": "+v6", 14 | "has-elf-tls": true, 15 | "linker": "ld.lld", 16 | "linker-flavor": "ld", 17 | "llvm-target": "arm-unknown-linux-eabi", 18 | "max-atomic-width": 64, 19 | "os": "linux", 20 | "panic-strategy": "abort", 21 | "pre-link-args": { 22 | "gcc": [ 23 | "-Wl,--as-needed", 24 | "-Wl,-z,noexecstack", 25 | "-nostartfiles" 26 | ] 27 | }, 28 | "target-c-int-width": "32", 29 | "target-endian": "little", 30 | "target-family": "unix", 31 | "target-pointer-width": "32", 32 | "vendor": "unknown" 33 | } 34 | -------------------------------------------------------------------------------- /docker/arm-unknown-linux-steedeabi/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY qemu.sh / 17 | RUN bash /qemu.sh 2.10.1 arm 18 | 19 | COPY arm-unknown-linux-steedeabi.json /json 20 | 21 | ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_STEEDEABI_RUNNER=qemu-arm \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/arm-unknown-linux-steedeabihf.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi-blacklist": [ 3 | "stdcall", 4 | "fastcall", 5 | "vectorcall", 6 | "win64", 7 | "sysv64" 8 | ], 9 | "arch": "arm", 10 | "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", 11 | "env": "steed", 12 | "executables": true, 13 | "features": "+v6,+vfp2", 14 | "has-elf-tls": true, 15 | "linker": "ld.lld", 16 | "linker-flavor": "ld", 17 | "llvm-target": "arm-unknown-linux-eabihf", 18 | "max-atomic-width": 64, 19 | "os": "linux", 20 | "panic-strategy": "abort", 21 | "pre-link-args": { 22 | "gcc": [ 23 | "-Wl,--as-needed", 24 | "-Wl,-z,noexecstack", 25 | "-nostartfiles" 26 | ] 27 | }, 28 | "target-c-int-width": "32", 29 | "target-endian": "little", 30 | "target-family": "unix", 31 | "target-pointer-width": "32", 32 | "vendor": "unknown" 33 | } 34 | -------------------------------------------------------------------------------- /docker/arm-unknown-linux-steedeabihf/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY qemu.sh / 17 | RUN bash /qemu.sh 2.10.1 arm 18 | 19 | COPY arm-unknown-linux-steedeabihf.json /json 20 | 21 | ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_STEEDEABIHF_RUNNER=qemu-arm \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/armv7-unknown-linux-steedeabihf.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi-blacklist": [ 3 | "stdcall", 4 | "fastcall", 5 | "vectorcall", 6 | "win64", 7 | "sysv64" 8 | ], 9 | "arch": "arm", 10 | "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", 11 | "env": "steed", 12 | "executables": true, 13 | "features": "+v7,+vfp3,+d16,+thumb2,-neon", 14 | "has-elf-tls": true, 15 | "linker": "ld.lld", 16 | "linker-flavor": "ld", 17 | "llvm-target": "armv7-unknown-linux-eabihf", 18 | "max-atomic-width": 64, 19 | "os": "linux", 20 | "panic-strategy": "abort", 21 | "pre-link-args": { 22 | "gcc": [ 23 | "-Wl,--as-needed", 24 | "-Wl,-z,noexecstack", 25 | "-nostartfiles" 26 | ] 27 | }, 28 | "target-c-int-width": "32", 29 | "target-endian": "little", 30 | "target-family": "unix", 31 | "target-pointer-width": "32", 32 | "vendor": "unknown" 33 | } 34 | -------------------------------------------------------------------------------- /docker/armv7-unknown-linux-steedeabihf/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY qemu.sh / 17 | RUN bash /qemu.sh 2.10.1 arm 18 | 19 | COPY armv7-unknown-linux-steedeabihf.json /json 20 | 21 | ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_STEEDEABIHF_RUNNER=qemu-arm \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/i686-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "x86", 3 | "cpu": "pentium4", 4 | "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", 5 | "env": "steed", 6 | "executables": true, 7 | "has-elf-tls": true, 8 | "linker": "ld.lld", 9 | "linker-flavor": "ld", 10 | "llvm-target": "i686-unknown-linux", 11 | "max-atomic-width": 64, 12 | "os": "linux", 13 | "panic-strategy": "abort", 14 | "pre-link-args": { 15 | "gcc": [ 16 | "-Wl,--as-needed", 17 | "-Wl,-z,noexecstack", 18 | "-m32", 19 | "-nostartfiles" 20 | ] 21 | }, 22 | "target-c-int-width": "32", 23 | "target-endian": "little", 24 | "target-family": "unix", 25 | "target-pointer-width": "32", 26 | "vendor": "unknown" 27 | } 28 | -------------------------------------------------------------------------------- /docker/i686-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY i686-unknown-linux-steed.json /json 17 | 18 | ENV RUST_TARGET_PATH=/json 19 | -------------------------------------------------------------------------------- /docker/lld.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | main() { 4 | local dependencies=( 5 | ca-certificates 6 | curl 7 | ) 8 | 9 | apt-get update 10 | local purge_list=() 11 | for dep in ${dependencies[@]}; do 12 | if ! dpkg -L $dep; then 13 | apt-get install --no-install-recommends -y $dep 14 | purge_list+=( $dep ) 15 | fi 16 | done 17 | 18 | cat <>/etc/apt/sources.list 19 | deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main 20 | deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main 21 | EOF 22 | 23 | curl -L http://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - 24 | apt-get update 25 | apt-get install --no-install-recommends -y lld-5.0 26 | ln -s ld.lld-5.0 /usr/bin/ld.lld 27 | 28 | # Clean up 29 | apt-get purge --auto-remove -y ${purge_list[@]} 30 | 31 | rm $0 32 | } 33 | 34 | main "${@}" 35 | -------------------------------------------------------------------------------- /docker/mips-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "mips", 3 | "cpu": "mips32r2", 4 | "data-layout": "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", 5 | "env": "steed", 6 | "executables": true, 7 | "has-elf-tls": true, 8 | "linker": "ld.lld", 9 | "linker-flavor": "ld", 10 | "llvm-target": "mips-unknown-linux", 11 | "max-atomic-width": 32, 12 | "os": "linux", 13 | "panic-strategy": "abort", 14 | "pre-link-args": { 15 | "gcc": [ 16 | "-Wl,--as-needed", 17 | "-Wl,-z,noexecstack", 18 | "-nostartfiles" 19 | ] 20 | }, 21 | "relocation-model": "static", 22 | "target-c-int-width": "32", 23 | "target-endian": "big", 24 | "target-family": "unix", 25 | "target-pointer-width": "32", 26 | "vendor": "unknown" 27 | } 28 | -------------------------------------------------------------------------------- /docker/mips-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY qemu.sh / 17 | RUN bash /qemu.sh 2.10.1 mips 18 | 19 | COPY mips-unknown-linux-steed.json /json 20 | 21 | ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_STEED_RUNNER=qemu-mips \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/mipsel-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "mips", 3 | "cpu": "mips32", 4 | "data-layout": "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", 5 | "env": "steed", 6 | "executables": true, 7 | "has-elf-tls": true, 8 | "linker": "ld.lld", 9 | "linker-flavor": "ld", 10 | "llvm-target": "mipsel-unknown-linux", 11 | "max-atomic-width": 32, 12 | "os": "linux", 13 | "panic-strategy": "abort", 14 | "pre-link-args": { 15 | "gcc": [ 16 | "-Wl,--as-needed", 17 | "-Wl,-z,noexecstack", 18 | "-nostartfiles" 19 | ] 20 | }, 21 | "target-c-int-width": "32", 22 | "relocation-model": "static", 23 | "target-endian": "little", 24 | "target-family": "unix", 25 | "target-pointer-width": "32", 26 | "vendor": "unknown" 27 | } 28 | -------------------------------------------------------------------------------- /docker/mipsel-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY qemu.sh / 17 | RUN bash /qemu.sh 2.10.1 mipsel 18 | 19 | COPY mipsel-unknown-linux-steed.json /json 20 | 21 | ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_STEED_RUNNER=qemu-mipsel \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/powerpc-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "powerpc", 3 | "data-layout": "E-m:e-p:32:32-i64:64-n32", 4 | "env": "steed", 5 | "executables": true, 6 | "has-elf-tls": true, 7 | "linker-flavor": "gcc", 8 | "llvm-target": "powerpc-unknown-linux", 9 | "max-atomic-width": 32, 10 | "os": "linux", 11 | "panic-strategy": "abort", 12 | "pre-link-args": { 13 | "gcc": [ 14 | "-Wl,--as-needed", 15 | "-Wl,-z,noexecstack", 16 | "-m32", 17 | "-nostartfiles" 18 | ] 19 | }, 20 | "target-c-int-width": "32", 21 | "target-endian": "big", 22 | "target-family": "unix", 23 | "target-pointer-width": "32", 24 | "vendor": "unknown" 25 | } 26 | -------------------------------------------------------------------------------- /docker/powerpc-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY qemu.sh / 14 | RUN apt-get install -y --no-install-recommends \ 15 | gcc-powerpc-linux-gnu && \ 16 | bash /qemu.sh 2.10.1 ppc 17 | 18 | COPY powerpc-unknown-linux-steed.json /json 19 | 20 | ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_STEED_RUNNER=qemu-ppc \ 21 | RUST_TARGET_PATH=/json \ 22 | RUST_TEST_THREADS=1 23 | -------------------------------------------------------------------------------- /docker/powerpc64-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "powerpc64", 3 | "cpu": "ppc64", 4 | "data-layout": "E-m:e-i64:64-n32:64", 5 | "env": "steed", 6 | "executables": true, 7 | "has-elf-tls": true, 8 | "linker-flavor": "gcc", 9 | "llvm-target": "powerpc64-unknown-linux", 10 | "max-atomic-width": 64, 11 | "os": "linux", 12 | "panic-strategy": "abort", 13 | "pre-link-args": { 14 | "gcc": [ 15 | "-Wl,--as-needed", 16 | "-Wl,-z,noexecstack", 17 | "-m64", 18 | "-nostartfiles" 19 | ] 20 | }, 21 | "target-c-int-width": "32", 22 | "target-endian": "big", 23 | "target-family": "unix", 24 | "target-pointer-width": "64", 25 | "vendor": "unknown" 26 | } 27 | -------------------------------------------------------------------------------- /docker/powerpc64-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY qemu.sh / 14 | RUN apt-get install -y --no-install-recommends \ 15 | gcc-powerpc64-linux-gnu && \ 16 | bash /qemu.sh 2.10.1 ppc64 17 | 18 | COPY powerpc64-unknown-linux-steed.json /json 19 | 20 | ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_STEED_LINKER=powerpc64-linux-gnu-gcc \ 21 | CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_STEED_RUNNER=qemu-ppc64 \ 22 | RUST_TARGET_PATH=/json \ 23 | RUST_TEST_THREADS=1 24 | -------------------------------------------------------------------------------- /docker/powerpc64le-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "powerpc64", 3 | "cpu": "ppc64le", 4 | "data-layout": "e-m:e-i64:64-n32:64", 5 | "env": "steed", 6 | "executables": true, 7 | "has-elf-tls": true, 8 | "linker-flavor": "gcc", 9 | "llvm-target": "powerpc64le-unknown-linux", 10 | "max-atomic-width": 64, 11 | "os": "linux", 12 | "panic-strategy": "abort", 13 | "pre-link-args": { 14 | "gcc": [ 15 | "-Wl,--as-needed", 16 | "-Wl,-z,noexecstack", 17 | "-m64", 18 | "-nostartfiles" 19 | ] 20 | }, 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-family": "unix", 24 | "target-pointer-width": "64", 25 | "vendor": "unknown" 26 | } 27 | -------------------------------------------------------------------------------- /docker/powerpc64le-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY qemu.sh / 14 | RUN apt-get install -y --no-install-recommends \ 15 | gcc-powerpc64le-linux-gnu && \ 16 | bash /qemu.sh 2.10.1 ppc64le 17 | 18 | COPY powerpc64le-unknown-linux-steed.json /json 19 | 20 | ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_STEED_RUNNER=qemu-ppc64le \ 21 | RUST_TARGET_PATH=/json \ 22 | RUST_TEST_THREADS=1 23 | -------------------------------------------------------------------------------- /docker/qemu.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | main() { 4 | local arch=$2 \ 5 | td=$(mktemp -d) \ 6 | version=$1 7 | 8 | local dependencies=( 9 | autoconf 10 | automake 11 | bzip2 12 | curl 13 | g++ 14 | libglib2.0-dev 15 | libtool 16 | make 17 | pkg-config 18 | zlib1g-dev 19 | ) 20 | 21 | apt-get update 22 | local purge_list=() 23 | for dep in ${dependencies[@]}; do 24 | dpkg -L $dep || ( 25 | apt-get install --no-install-recommends -y $dep && 26 | purge_list+=( $dep ) 27 | ) 28 | done 29 | 30 | pushd $td 31 | 32 | curl -L http://download.qemu-project.org/qemu-$version.tar.xz | \ 33 | tar --strip-components=1 -xJ 34 | ./configure \ 35 | --disable-kvm \ 36 | --disable-vnc \ 37 | --enable-user \ 38 | --static \ 39 | --target-list=$arch-linux-user 40 | nice make -j$(nproc) 41 | make install 42 | 43 | # HACK the binfmt_misc interpreter we'll use expects the QEMU binary to be 44 | # in /usr/bin. Create an appropriate symlink 45 | ln -s /usr/local/bin/qemu-$arch /usr/bin/qemu-$arch-static 46 | 47 | # Clean up 48 | apt-get purge --auto-remove -y ${purge_list[@]} 49 | 50 | popd 51 | 52 | rm -rf $td 53 | rm $0 54 | } 55 | 56 | main "${@}" 57 | -------------------------------------------------------------------------------- /docker/x86_64-unknown-linux-steed.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "x86_64", 3 | "cpu": "x86-64", 4 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", 5 | "env": "steed", 6 | "executables": true, 7 | "has-elf-tls": true, 8 | "linker": "ld.lld", 9 | "linker-flavor": "ld", 10 | "llvm-target": "x86_64-unknown-linux", 11 | "max-atomic-width": 64, 12 | "os": "linux", 13 | "panic-strategy": "abort", 14 | "pre-link-args": { 15 | "gcc": [ 16 | "-Wl,--as-needed", 17 | "-Wl,-z,noexecstack", 18 | "-m64", 19 | "-nostartfiles" 20 | ] 21 | }, 22 | "target-c-int-width": "32", 23 | "target-endian": "little", 24 | "target-family": "unix", 25 | "target-pointer-width": "64", 26 | "vendor": "unknown" 27 | } 28 | -------------------------------------------------------------------------------- /docker/x86_64-unknown-linux-steed/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | gcc \ 7 | libc6-dev && \ 8 | mkdir /json 9 | 10 | COPY xargo.sh / 11 | RUN bash /xargo.sh 12 | 13 | COPY lld.sh / 14 | RUN bash /lld.sh 15 | 16 | COPY x86_64-unknown-linux-steed.json /json 17 | 18 | ENV RUST_TARGET_PATH=/json 19 | -------------------------------------------------------------------------------- /docker/xargo.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | main() { 4 | local tag=v0.3.6 5 | local dependencies=( 6 | ca-certificates 7 | curl 8 | ) 9 | 10 | apt-get update 11 | local purge_list=() 12 | for dep in ${dependencies[@]}; do 13 | if ! dpkg -L $dep; then 14 | apt-get install --no-install-recommends -y $dep 15 | purge_list+=( $dep ) 16 | fi 17 | done 18 | 19 | curl -LSfs http://japaric.github.io/trust/install.sh | \ 20 | sh -s -- \ 21 | --git japaric/xargo \ 22 | --tag $tag \ 23 | --target x86_64-unknown-linux-gnu \ 24 | --to /usr/bin 25 | 26 | # Clean up 27 | apt-get purge --auto-remove -y ${purge_list[@]} 28 | 29 | rm $0 30 | } 31 | 32 | main "${@}" 33 | -------------------------------------------------------------------------------- /examples/_llseek.rs: -------------------------------------------------------------------------------- 1 | use std::fs::OpenOptions; 2 | use std::io::{self, Read, Seek, SeekFrom, Write}; 3 | use std::process; 4 | 5 | pub fn main() { 6 | let f = OpenOptions::new() 7 | .read(true) 8 | .write(true) 9 | .create(true) 10 | .truncate(true) 11 | .open("/target/_llseek") 12 | .unwrap(); 13 | (&f).write(b"Can you find me?\n").unwrap(); 14 | let mut buffer = [0; 2]; 15 | (&f).seek(SeekFrom::Current(-4)).unwrap(); 16 | let n = (&f).read(&mut buffer).unwrap(); 17 | let read = &buffer[..n]; 18 | io::stdout().write_all(read).unwrap(); 19 | io::stdout().write_all(b"\n").unwrap(); 20 | if read != b"me" { 21 | process::exit(1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/args.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | fn main() { 4 | for arg in env::args() { 5 | println!("{:?}", arg); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/canonicalize.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | 3 | fn main() { 4 | println!("{}", fs::canonicalize(".").unwrap().display()); 5 | } 6 | -------------------------------------------------------------------------------- /examples/chdir.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | fn main() { 3 | env::set_current_dir("..").unwrap(); 4 | } 5 | -------------------------------------------------------------------------------- /examples/create.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::Write; 3 | 4 | fn main() { 5 | let mut f = File::create("/target/hello").unwrap(); 6 | f.write_all(b"Hello, world!\n").unwrap(); 7 | } 8 | -------------------------------------------------------------------------------- /examples/dup.rs: -------------------------------------------------------------------------------- 1 | use std::fs::OpenOptions; 2 | use std::io::Read; 3 | use std::io::Write; 4 | use std::io; 5 | use std::os::unix::fs::FileExt; 6 | use std::process; 7 | 8 | fn main() { 9 | let f = OpenOptions::new() 10 | .read(true) 11 | .write(true) 12 | .create(true) 13 | .truncate(true) 14 | .open("/target/dup") 15 | .unwrap(); 16 | let g = f.try_clone().unwrap(); 17 | (&f).write_all(b"Do you copy?\n").unwrap(); 18 | let mut buffer = [0; 256]; 19 | let n = (&g).read(&mut buffer).unwrap(); 20 | { 21 | let read = &buffer[..n]; 22 | if read != b"" { 23 | process::exit(1); 24 | } 25 | } 26 | let n = g.read_at(&mut buffer, 0).unwrap(); 27 | let read = &buffer[..n]; 28 | io::stdout().write_all(read).unwrap(); 29 | if read != b"Do you copy?\n" { 30 | process::exit(1); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/echo.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::{Read, Write}; 3 | 4 | fn main() { 5 | let mut buffer = [0; 256]; 6 | let mut stdin = io::stdin(); 7 | let n = stdin.read(&mut buffer).unwrap(); 8 | io::stdout().write_all(&buffer[..n]).unwrap(); 9 | } 10 | -------------------------------------------------------------------------------- /examples/env.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | fn main() { 3 | println!("{}", env::current_exe().unwrap().display()); 4 | println!("{}", env::temp_dir().display()); 5 | for (k, v) in env::vars_os() { 6 | println!("{:?}: {:?}", k, v); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/execve.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | fn main() { 4 | let result = Command::new("/bin/echo") 5 | .arg("Execution of /bin/echo successful") 6 | .spawn() 7 | .unwrap() 8 | .wait() 9 | .unwrap(); 10 | assert!(result.success()); 11 | } 12 | -------------------------------------------------------------------------------- /examples/format.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::Write; 3 | 4 | fn main() { 5 | io::stdout() 6 | .write_all(format!("{} + {} = {}\n", 1, 1, 1 + 1).as_bytes()) 7 | .unwrap(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /examples/hashmap.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let mut h = HashMap::new(); 5 | h.insert("foo", "bar"); 6 | h.insert("keks", "baz"); 7 | println!("{:?}", h); 8 | } 9 | -------------------------------------------------------------------------------- /examples/hello.rs: -------------------------------------------------------------------------------- 1 | use std::{io, process}; 2 | use std::io::Write; 3 | 4 | fn main() { 5 | if io::stdout().write_all(b"Hello, world!\n").is_err() { 6 | process::exit(1) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/instant.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | fn main() { 4 | let now = Instant::now(); 5 | let elapsed = now.elapsed(); 6 | 7 | println!("{:?}", elapsed); 8 | } 9 | -------------------------------------------------------------------------------- /examples/ls.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::path::Path; 3 | 4 | pub fn main() { 5 | for f in fs::read_dir("/").unwrap() { 6 | let f = f.unwrap(); 7 | println!("{}", Path::new(&f.file_name()).display()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/mutex.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Mutex; 2 | 3 | fn common() -> Mutex { 4 | let m = Mutex::new(0); 5 | { 6 | *m.lock().unwrap() = 1; 7 | println!("{}", *m.lock().unwrap()); 8 | } 9 | m 10 | } 11 | 12 | #[cfg(not(any(target_arch = "aarch64", 13 | target_arch = "arm", 14 | target_arch = "powerpc", 15 | target_arch = "x86", 16 | target_arch = "x86_64")))] 17 | fn main() { 18 | common(); 19 | println!("success"); 20 | } 21 | 22 | #[cfg(any(target_arch = "aarch64", 23 | target_arch = "arm", 24 | target_arch = "powerpc", 25 | target_arch = "x86", 26 | target_arch = "x86_64"))] 27 | fn main() { 28 | use std::sync::Arc; 29 | use std::thread; 30 | use std::time::Duration; 31 | let m = Arc::new(common()); 32 | let m2 = m.clone(); 33 | 34 | let guard = m.lock().unwrap(); 35 | 36 | let t = thread::spawn(move || { 37 | let _ = m2.lock().unwrap(); 38 | }); 39 | 40 | thread::sleep(Duration::new(1, 0)); 41 | drop(guard); 42 | 43 | t.join().unwrap(); 44 | println!("success"); 45 | } 46 | -------------------------------------------------------------------------------- /examples/one.rs: -------------------------------------------------------------------------------- 1 | use std::process; 2 | 3 | fn main() { 4 | process::exit(1) 5 | } 6 | -------------------------------------------------------------------------------- /examples/open.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{Read, Write}; 3 | use std::io; 4 | 5 | fn main() { 6 | let mut f = File::open("/target/hello").unwrap(); 7 | let mut buffer = [0; 256]; 8 | let n = f.read(&mut buffer).unwrap(); 9 | io::stdout().write_all(&buffer[..n]).unwrap(); 10 | } 11 | -------------------------------------------------------------------------------- /examples/panic.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | panic!() 3 | } 4 | -------------------------------------------------------------------------------- /examples/preadwrite.rs: -------------------------------------------------------------------------------- 1 | use std::fs::OpenOptions; 2 | use std::io::{self, Write}; 3 | use std::os::unix::fs::FileExt; 4 | use std::process; 5 | 6 | pub fn main() { 7 | let f = OpenOptions::new() 8 | .read(true) 9 | .write(true) 10 | .create(true) 11 | .truncate(true) 12 | .open("/target/readwrite") 13 | .unwrap(); 14 | f.write_at(b"She says: Hi?\nWhat do you say?\n", 0).unwrap(); 15 | f.set_len(14).unwrap(); 16 | let mut buffer = [0; 256]; 17 | let n = f.read_at(&mut buffer, 10).unwrap(); 18 | let read = &buffer[..n]; 19 | io::stdout().write_all(read).unwrap(); 20 | if read != b"Hi?\n" { 21 | process::exit(1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/print.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("{} + {} = {}", 1, 1, 1 + 1); 3 | } 4 | -------------------------------------------------------------------------------- /examples/stat.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::process; 5 | 6 | pub fn main() { 7 | let path = "/target/stat"; 8 | let content = b"Test stat\n"; 9 | let size = content.len() as u64; 10 | let file = File::create(path).unwrap(); 11 | (&file).write_all(b"Test stat\n").unwrap(); 12 | let f = file.metadata().unwrap(); 13 | let s = fs::metadata(path).unwrap(); 14 | let l = fs::symlink_metadata(path).unwrap(); 15 | println!("{} {} {} {} {:?}", size, f.len(), s.len(), l.len(), file); 16 | if f.len() != size || s.len() != size || l.len() != size { 17 | process::exit(1); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/stderr.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::Write; 3 | 4 | fn main() { 5 | io::stderr().write_all(b"Hello, world!\n").ok(); 6 | } 7 | -------------------------------------------------------------------------------- /examples/system-time.rs: -------------------------------------------------------------------------------- 1 | use std::time::SystemTime; 2 | 3 | fn main() { 4 | let now = SystemTime::now(); 5 | 6 | println!("{:?}", now); 7 | } 8 | -------------------------------------------------------------------------------- /examples/tcp_listen_connect.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write}; 2 | use std::net::{SocketAddr, IpAddr, Ipv4Addr, TcpStream, TcpListener}; 3 | 4 | fn main () { 5 | let localhost = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); 6 | let addr = SocketAddr::new(localhost, 12345); 7 | let listener = TcpListener::bind(addr).expect("bind"); 8 | 9 | let mut stream = TcpStream::connect(addr).expect("connect"); 10 | let request = b"Hello, World!!!"; 11 | stream.write(request).expect("write"); 12 | drop(stream); 13 | 14 | let (mut accepted, _peer_addr) = listener.accept().expect("accept"); 15 | let mut response = Vec::new(); 16 | accepted.read_to_end(&mut response).expect("read_to_end"); 17 | assert_eq!(request.to_vec(), response); 18 | } 19 | -------------------------------------------------------------------------------- /examples/thread.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(any(target_arch = "aarch64", 2 | target_arch = "arm", 3 | target_arch = "powerpc", 4 | target_arch = "x86", 5 | target_arch = "x86_64")))] 6 | fn main() { 7 | } 8 | 9 | #[cfg(any(target_arch = "aarch64", 10 | target_arch = "arm", 11 | target_arch = "powerpc", 12 | target_arch = "x86", 13 | target_arch = "x86_64"))] 14 | fn main() { 15 | use std::io::{self, Write}; 16 | use std::thread; 17 | 18 | thread::spawn(|| { 19 | io::stdout().write_all(b"Hello, world!\n").unwrap(); 20 | }).join().unwrap(); 21 | } 22 | -------------------------------------------------------------------------------- /examples/vec.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("{:?}", vec![0, 1, 2, 3]); 3 | } 4 | -------------------------------------------------------------------------------- /examples/zero.rs: -------------------------------------------------------------------------------- 1 | fn main() {} 2 | -------------------------------------------------------------------------------- /generate/errno.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Usage: 3 | # errno.py path/to/linux 4 | from __future__ import print_function 5 | 6 | import argparse 7 | from collections import defaultdict, namedtuple, OrderedDict 8 | import os.path 9 | import re 10 | import sys 11 | 12 | DEFINE_REGEX=re.compile(r"^#define\s+(?PE[A-Z0-9]+)\s+(?P\w+)\s*(\/\* (?P.*) \*\/\s*)?$") 13 | 14 | ErrnoValue = namedtuple('ErrnoValue', 'name value comment') 15 | 16 | def parse_line(line): 17 | m = DEFINE_REGEX.match(line) 18 | if m: 19 | return ErrnoValue(**m.groupdict()) 20 | 21 | def parse_file(path): 22 | parsed = (parse_line(line) for line in open(path)) 23 | return [p for p in parsed if p is not None] 24 | 25 | def print_module(name, l): 26 | print() 27 | print("#[allow(dead_code)]") 28 | print("mod {} {{".format(name)) 29 | print(" use libc::c_int;") 30 | print() 31 | for v in l: 32 | prefix = "" 33 | try: 34 | int(v.value) 35 | except ValueError: 36 | prefix = "super::" 37 | print(" pub const {name}: c_int = {prefix}{value};".format(prefix=prefix, **v._asdict())) 38 | print("}") 39 | 40 | def main(): 41 | parser = argparse.ArgumentParser(description="Generate Linux errno constants") 42 | parser.add_argument('linux_source', metavar="LINUX_SOURCE", help="Path to the Linux source code") 43 | parser.add_argument('arch_mapping', metavar="ARCH_MAPPING", nargs='*', help="Add an architecture mapping, `:`, e.g. `mips:mips,mips64`") 44 | args = parser.parse_args() 45 | 46 | arch_mapping = defaultdict(lambda: []) 47 | for a in args.arch_mapping: 48 | linux, rust = a.split(':', 1) 49 | rust = rust.split(',') 50 | arch_mapping[linux] += rust 51 | 52 | def parse_file_rel(path): 53 | return parse_file(os.path.join(args.linux_source, path)) 54 | 55 | base = parse_file_rel("include/uapi/asm-generic/errno-base.h") 56 | generic = parse_file_rel("include/uapi/asm-generic/errno.h") 57 | arch = {a: parse_file_rel("arch/{}/include/uapi/asm/errno.h".format(a)) for a in arch_mapping} 58 | 59 | print("// NOTE: The following code was generated by \"generate/errno.py\",") 60 | print("// do not edit directly!") 61 | print() 62 | print("// Generating command line:") 63 | print("// generate/errno.py path/to/linux/src {} > src/linux/errno.rs".format(" ".join(args.arch_mapping))) 64 | print() 65 | print("pub use self::base::*;") 66 | print() 67 | if arch: 68 | print("#[cfg(not(any({})))]".format(",\n ".join( 69 | 'target_arch = "{}"'.format(a) for a in sum(arch_mapping.values(), []) 70 | ))) 71 | print("pub use self::generic::*;") 72 | for linux, rust in arch_mapping.items(): 73 | print() 74 | print("#[cfg(any({}))]".format(",\n ".join( 75 | 'target_arch = "{}"'.format(a) for a in rust 76 | ))) 77 | print("pub use self::{}::*;".format(linux)) 78 | 79 | print_module("base", base) 80 | print_module("generic", generic) 81 | for a, errnos in arch.items(): 82 | print_module(a, errnos) 83 | print() 84 | print("// Some errno values coincide on some platforms, while they don't on others.") 85 | print("#[allow(unreachable_patterns)]") 86 | print("pub fn error_string(errno: i32) -> Option<&'static str> {") 87 | print(" Some(match errno {") 88 | constants = OrderedDict((v.name, v) for v in base + generic) 89 | for v in constants.values(): 90 | if v.comment is None: 91 | v = v._replace(comment=constants[v.value].comment) 92 | print(" {name} => \"{comment}\",".format(**v._asdict())) 93 | print(" _ => return None,") 94 | print(" })") 95 | print("}") 96 | 97 | 98 | if __name__ == '__main__': 99 | main() 100 | -------------------------------------------------------------------------------- /naive_ralloc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "naive_ralloc" 3 | version = "0.1.0" 4 | authors = ["author"] 5 | 6 | [dependencies] 7 | sc = "0.2.0" 8 | -------------------------------------------------------------------------------- /naive_ralloc/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(alloc)] 2 | #![feature(allocator_api)] 3 | #![feature(global_allocator)] 4 | #![no_std] 5 | 6 | extern crate alloc; 7 | #[macro_use] 8 | extern crate sc; 9 | 10 | use alloc::allocator::{Alloc, AllocErr, Layout}; 11 | 12 | struct Allocator; 13 | 14 | unsafe impl<'a> Alloc for &'a Allocator { 15 | unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { 16 | let size = layout.size(); 17 | let align = layout.align(); 18 | let mask = align - 1; 19 | 20 | let cur = brk(0); 21 | let aligned = (cur + mask) & !mask; 22 | let new = aligned + size; 23 | let actual = brk(new); 24 | if actual < new { 25 | Err(AllocErr::Exhausted { request: layout }) 26 | } else { 27 | Ok(aligned as *mut u8) 28 | } 29 | } 30 | 31 | unsafe fn dealloc(&mut self, _ptr: *mut u8, _layout: Layout) { 32 | // no deallocation 33 | } 34 | } 35 | 36 | #[global_allocator] 37 | static GLOBAL: Allocator = Allocator; 38 | 39 | // fs/mmap.c 40 | pub unsafe fn brk(brk: usize) -> usize { 41 | syscall!(BRK, brk) 42 | } 43 | -------------------------------------------------------------------------------- /src/collections/hash/bench.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![cfg(test)] 12 | 13 | extern crate test; 14 | 15 | use self::test::Bencher; 16 | 17 | #[bench] 18 | fn new_drop(b: &mut Bencher) { 19 | use super::map::HashMap; 20 | 21 | b.iter(|| { 22 | let m: HashMap = HashMap::new(); 23 | assert_eq!(m.len(), 0); 24 | }) 25 | } 26 | 27 | #[bench] 28 | fn new_insert_drop(b: &mut Bencher) { 29 | use super::map::HashMap; 30 | 31 | b.iter(|| { 32 | let mut m = HashMap::new(); 33 | m.insert(0, 0); 34 | assert_eq!(m.len(), 1); 35 | }) 36 | } 37 | 38 | #[bench] 39 | fn grow_by_insertion(b: &mut Bencher) { 40 | use super::map::HashMap; 41 | 42 | let mut m = HashMap::new(); 43 | 44 | for i in 1..1001 { 45 | m.insert(i, i); 46 | } 47 | 48 | let mut k = 1001; 49 | 50 | b.iter(|| { 51 | m.insert(k, k); 52 | k += 1; 53 | }); 54 | } 55 | 56 | #[bench] 57 | fn find_existing(b: &mut Bencher) { 58 | use super::map::HashMap; 59 | 60 | let mut m = HashMap::new(); 61 | 62 | for i in 1..1001 { 63 | m.insert(i, i); 64 | } 65 | 66 | b.iter(|| { 67 | for i in 1..1001 { 68 | m.contains_key(&i); 69 | } 70 | }); 71 | } 72 | 73 | #[bench] 74 | fn find_nonexisting(b: &mut Bencher) { 75 | use super::map::HashMap; 76 | 77 | let mut m = HashMap::new(); 78 | 79 | for i in 1..1001 { 80 | m.insert(i, i); 81 | } 82 | 83 | b.iter(|| { 84 | for i in 1001..2001 { 85 | m.contains_key(&i); 86 | } 87 | }); 88 | } 89 | 90 | #[bench] 91 | fn hashmap_as_queue(b: &mut Bencher) { 92 | use super::map::HashMap; 93 | 94 | let mut m = HashMap::new(); 95 | 96 | for i in 1..1001 { 97 | m.insert(i, i); 98 | } 99 | 100 | let mut k = 1; 101 | 102 | b.iter(|| { 103 | m.remove(&k); 104 | m.insert(k + 1000, k + 1000); 105 | k += 1; 106 | }); 107 | } 108 | 109 | #[bench] 110 | fn get_remove_insert(b: &mut Bencher) { 111 | use super::map::HashMap; 112 | 113 | let mut m = HashMap::new(); 114 | 115 | for i in 1..1001 { 116 | m.insert(i, i); 117 | } 118 | 119 | let mut k = 1; 120 | 121 | b.iter(|| { 122 | m.get(&(k + 400)); 123 | m.get(&(k + 2000)); 124 | m.remove(&k); 125 | m.insert(k + 1000, k + 1000); 126 | k += 1; 127 | }) 128 | } 129 | -------------------------------------------------------------------------------- /src/collections/hash/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Unordered containers, implemented as hash-tables 12 | 13 | mod bench; 14 | mod table; 15 | pub mod map; 16 | pub mod set; 17 | 18 | trait Recover { 19 | type Key; 20 | 21 | fn get(&self, key: &Q) -> Option<&Self::Key>; 22 | fn take(&mut self, key: &Q) -> Option; 23 | fn replace(&mut self, key: Self::Key) -> Option; 24 | } 25 | -------------------------------------------------------------------------------- /src/ctypes.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(unused)] 3 | 4 | #[cfg(any(target_arch = "aarch64", 5 | target_arch = "arm", 6 | target_arch = "powerpc", 7 | target_arch = "powerpc64"))] 8 | pub type c_char = u8; 9 | 10 | #[cfg(any(target_arch = "mips", 11 | target_arch = "mips64", 12 | target_arch = "sparc64", 13 | target_arch = "x86", 14 | target_arch = "x86_64"))] 15 | pub type c_char = i8; 16 | 17 | #[cfg(target_pointer_width = "32")] pub type c_long = i32; 18 | #[cfg(target_pointer_width = "64")] pub type c_long = i64; 19 | #[cfg(target_pointer_width = "32")] pub type c_ulong = u32; 20 | #[cfg(target_pointer_width = "64")] pub type c_ulong = u64; 21 | 22 | pub type c_uchar = u8; 23 | pub type c_schar = i8; 24 | pub type c_short = i16; 25 | pub type c_ushort = u16; 26 | pub type c_int = i32; 27 | pub type c_uint = u32; 28 | pub type c_longlong = i64; 29 | pub type c_ulonglong = u64; 30 | pub type c_float = f32; 31 | pub type c_double = f64; 32 | 33 | pub type size_t = usize; 34 | pub type ssize_t = isize; 35 | 36 | pub type c_void = c_char; 37 | -------------------------------------------------------------------------------- /src/ffi/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Utilities related to FFI bindings. 12 | 13 | #![stable(feature = "rust1", since = "1.0.0")] 14 | 15 | #[stable(feature = "rust1", since = "1.0.0")] 16 | pub use self::c_str::{CString, CStr, NulError, IntoStringError}; 17 | #[stable(feature = "cstr_from_bytes", since = "1.10.0")] 18 | pub use self::c_str::{FromBytesWithNulError}; 19 | 20 | #[stable(feature = "rust1", since = "1.0.0")] 21 | pub use self::os_str::{OsString, OsStr}; 22 | 23 | mod c_str; 24 | mod os_str; 25 | -------------------------------------------------------------------------------- /src/io/lazy.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/japaric/steed/73f1ce2976164208f5c36b2b19652f8b7d98b671/src/io/lazy.rs -------------------------------------------------------------------------------- /src/io/prelude.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The I/O Prelude 12 | //! 13 | //! The purpose of this module is to alleviate imports of many common I/O traits 14 | //! by adding a glob import to the top of I/O heavy modules: 15 | //! 16 | //! ``` 17 | //! # #![allow(unused_imports)] 18 | //! use std::io::prelude::*; 19 | //! ``` 20 | 21 | #![stable(feature = "rust1", since = "1.0.0")] 22 | 23 | #[stable(feature = "rust1", since = "1.0.0")] 24 | pub use super::{Read, Write, BufRead, Seek}; 25 | -------------------------------------------------------------------------------- /src/io/stdio.rs: -------------------------------------------------------------------------------- 1 | #![stable(feature = "steed", since = "1.0.0")] 2 | 3 | use fmt; 4 | use io::{self, Error, Read, Write}; 5 | use libc::{self, c_int}; 6 | use str; 7 | 8 | const STDIN: c_int = 0; 9 | const STDOUT: c_int = 1; 10 | const STDERR: c_int = 2; 11 | 12 | #[stable(feature = "steed", since = "1.0.0")] 13 | pub struct Stderr { 14 | _0: (), 15 | } 16 | 17 | #[stable(feature = "steed", since = "1.0.0")] 18 | impl Write for Stderr { 19 | fn write(&mut self, buffer: &[u8]) -> io::Result { 20 | match unsafe { 21 | libc::write(STDERR, buffer.as_ptr() as *const _, buffer.len()) 22 | } { 23 | n if n >= 0 => Ok(n as usize), 24 | n => Err(Error::from_raw_os_error(-n as i32)), 25 | } 26 | } 27 | fn flush(&mut self) -> io::Result<()> { 28 | Ok(()) 29 | } 30 | } 31 | 32 | #[stable(feature = "steed", since = "1.0.0")] 33 | impl fmt::Write for Stderr { 34 | fn write_str(&mut self, s: &str) -> fmt::Result { 35 | self.write_all(s.as_bytes()).map_err(|_| fmt::Error) 36 | } 37 | } 38 | 39 | #[stable(feature = "steed", since = "1.0.0")] 40 | pub struct Stdin { 41 | _0: (), 42 | } 43 | 44 | #[stable(feature = "steed", since = "1.0.0")] 45 | impl Read for Stdin { 46 | fn read(&mut self, buffer: &mut [u8]) -> io::Result { 47 | match unsafe { 48 | libc::read(STDIN, buffer.as_mut_ptr() as *mut _, buffer.len()) 49 | } { 50 | n if n >= 0 => Ok(n as usize), 51 | n => Err(Error::from_raw_os_error(-n as i32)), 52 | } 53 | } 54 | } 55 | 56 | #[stable(feature = "steed", since = "1.0.0")] 57 | pub struct Stdout { 58 | _0: (), 59 | } 60 | 61 | #[stable(feature = "steed", since = "1.0.0")] 62 | impl Write for Stdout { 63 | fn write(&mut self, buffer: &[u8]) -> io::Result { 64 | match unsafe { 65 | libc::write(STDOUT, buffer.as_ptr() as *const _, buffer.len()) 66 | } { 67 | n if n >= 0 => Ok(n as usize), 68 | n => Err(Error::from_raw_os_error(-n as i32)), 69 | } 70 | } 71 | fn flush(&mut self) -> io::Result<()> { 72 | Ok(()) 73 | } 74 | } 75 | 76 | #[stable(feature = "steed", since = "1.0.0")] 77 | impl fmt::Write for Stdout { 78 | fn write_str(&mut self, s: &str) -> fmt::Result { 79 | self.write_all(s.as_bytes()).map_err(|_| fmt::Error) 80 | } 81 | } 82 | 83 | #[stable(feature = "steed", since = "1.0.0")] 84 | pub fn stderr() -> Stderr { 85 | Stderr { _0: () } 86 | } 87 | 88 | #[stable(feature = "steed", since = "1.0.0")] 89 | pub fn stdin() -> Stdin { 90 | Stdin { _0: () } 91 | } 92 | 93 | #[stable(feature = "steed", since = "1.0.0")] 94 | pub fn stdout() -> Stdout { 95 | Stdout { _0: () } 96 | } 97 | 98 | #[stable(feature = "steed", since = "1.0.0")] 99 | #[doc(hidden)] 100 | pub fn _print(args: fmt::Arguments) { 101 | if io::Write::write_fmt(&mut stdout(), args).is_err() { 102 | panic!("failed printing to stdout") 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(test, feature(rustc_private))] 2 | #![feature(alloc)] 3 | #![feature(allocator_api)] 4 | #![feature(allow_internal_unstable)] 5 | #![feature(asm)] 6 | #![feature(box_syntax)] 7 | #![feature(cfg_target_vendor)] 8 | #![feature(collections_range)] 9 | #![feature(compiler_builtins_lib)] 10 | #![feature(const_atomic_bool_new)] 11 | #![feature(const_atomic_u8_new)] 12 | #![feature(const_atomic_usize_new)] 13 | #![feature(const_fn)] 14 | #![feature(core_intrinsics)] 15 | #![feature(custom_attribute)] 16 | #![feature(dropck_eyepatch)] 17 | #![feature(dropck_parametricity)] 18 | #![feature(exact_size_is_empty)] 19 | #![feature(fnbox)] 20 | #![feature(fused)] 21 | #![feature(generic_param_attrs)] 22 | #![feature(global_asm)] 23 | #![feature(int_error_internals)] 24 | #![feature(integer_atomics)] 25 | #![feature(lang_items)] 26 | #![feature(macro_reexport)] 27 | #![feature(naked_functions)] 28 | #![feature(needs_drop)] 29 | #![feature(optin_builtin_traits)] 30 | #![feature(placement_new_protocol)] 31 | #![feature(prelude_import)] 32 | #![feature(rand)] 33 | #![feature(raw)] 34 | #![feature(shared)] 35 | #![feature(sip_hash_13)] 36 | #![feature(slice_concat_ext)] 37 | #![feature(slice_patterns)] 38 | #![feature(staged_api)] 39 | #![feature(str_internals)] 40 | #![feature(try_from)] 41 | #![feature(unicode)] 42 | #![feature(unique)] 43 | #![no_std] 44 | 45 | #![stable(feature = "rust1", since = "1.0.0")] 46 | 47 | // Explicitly import the prelude. The compiler uses this same unstable attribute 48 | // to import the prelude implicitly when building crates that depend on std. 49 | #[prelude_import] 50 | #[allow(unused)] 51 | use prelude::v1::*; 52 | 53 | // We want to reexport a few macros from core but libcore has already been 54 | // imported by the compiler (via our #[no_std] attribute) In this case we just 55 | // add a new crate name so we can attach the reexports to it. 56 | #[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, 57 | debug_assert_ne, panic, unreachable, unimplemented, write, 58 | writeln, try)] 59 | extern crate core as __core; 60 | 61 | extern crate alloc; 62 | #[macro_use] 63 | #[macro_reexport(vec, format)] 64 | extern crate alloc as core_collections; 65 | extern crate compiler_builtins; 66 | #[cfg(not(test))] 67 | #[cfg(feature = "ralloc")] 68 | extern crate ralloc; 69 | #[cfg(not(test))] 70 | #[cfg(feature = "naive_ralloc")] 71 | // this contains the global allocator (static variable) 72 | #[allow(unused_extern_crates)] 73 | extern crate naive_ralloc; 74 | #[macro_use] 75 | extern crate sc; 76 | extern crate std_unicode; 77 | extern crate rand as core_rand; 78 | #[cfg(test)] 79 | extern crate test; 80 | 81 | // Rust 1.16.0 82 | // The Rust prelude 83 | pub mod prelude; 84 | 85 | // Public module declarations and reexports 86 | #[stable(feature = "rust1", since = "1.0.0")] 87 | pub use core::any; 88 | #[stable(feature = "rust1", since = "1.0.0")] 89 | pub use core::cell; 90 | #[stable(feature = "rust1", since = "1.0.0")] 91 | pub use core::clone; 92 | #[stable(feature = "rust1", since = "1.0.0")] 93 | pub use core::cmp; 94 | #[stable(feature = "rust1", since = "1.0.0")] 95 | pub use core::convert; 96 | #[stable(feature = "rust1", since = "1.0.0")] 97 | pub use core::default; 98 | #[stable(feature = "rust1", since = "1.0.0")] 99 | pub use core::hash; 100 | #[stable(feature = "rust1", since = "1.0.0")] 101 | pub use core::intrinsics; 102 | #[stable(feature = "rust1", since = "1.0.0")] 103 | pub use core::iter; 104 | #[stable(feature = "rust1", since = "1.0.0")] 105 | pub use core::marker; 106 | #[stable(feature = "rust1", since = "1.0.0")] 107 | pub use core::mem; 108 | #[stable(feature = "rust1", since = "1.0.0")] 109 | pub use core::ops; 110 | #[stable(feature = "rust1", since = "1.0.0")] 111 | pub use core::ptr; 112 | #[stable(feature = "rust1", since = "1.0.0")] 113 | pub use core::raw; 114 | #[stable(feature = "rust1", since = "1.0.0")] 115 | pub use core::result; 116 | #[stable(feature = "rust1", since = "1.0.0")] 117 | pub use core::option; 118 | #[stable(feature = "rust1", since = "1.0.0")] 119 | pub use core::isize; 120 | #[stable(feature = "rust1", since = "1.0.0")] 121 | pub use core::i8; 122 | #[stable(feature = "rust1", since = "1.0.0")] 123 | pub use core::i16; 124 | #[stable(feature = "rust1", since = "1.0.0")] 125 | pub use core::i32; 126 | #[stable(feature = "rust1", since = "1.0.0")] 127 | pub use core::i64; 128 | #[stable(feature = "rust1", since = "1.0.0")] 129 | pub use core::usize; 130 | #[stable(feature = "rust1", since = "1.0.0")] 131 | pub use core::u8; 132 | #[stable(feature = "rust1", since = "1.0.0")] 133 | pub use core::u16; 134 | #[stable(feature = "rust1", since = "1.0.0")] 135 | pub use core::u32; 136 | #[stable(feature = "rust1", since = "1.0.0")] 137 | pub use core::u64; 138 | #[stable(feature = "rust1", since = "1.0.0")] 139 | pub use alloc::boxed; 140 | #[stable(feature = "rust1", since = "1.0.0")] 141 | pub use alloc::rc; 142 | #[stable(feature = "rust1", since = "1.0.0")] 143 | pub use core_collections::borrow; 144 | #[stable(feature = "rust1", since = "1.0.0")] 145 | pub use core_collections::fmt; 146 | #[stable(feature = "rust1", since = "1.0.0")] 147 | pub use core_collections::slice; 148 | #[stable(feature = "rust1", since = "1.0.0")] 149 | pub use core_collections::str; 150 | #[stable(feature = "rust1", since = "1.0.0")] 151 | pub use core_collections::string; 152 | #[stable(feature = "rust1", since = "1.0.0")] 153 | pub use core_collections::vec; 154 | #[stable(feature = "rust1", since = "1.0.0")] 155 | pub use std_unicode::char; 156 | 157 | // Rust 1.16.0 158 | #[macro_use] 159 | mod macros; 160 | 161 | pub mod sync; 162 | 163 | // Rust 1.16.0 164 | pub mod ascii; 165 | // Rust nightly 1.21.0 c11f689d2 (incomplete) 166 | pub mod collections; 167 | // Rust 1.16.0 (incomplete) 168 | pub mod env; 169 | // Rust 1.16.0 170 | pub mod error; 171 | // Rust 1.16.0 172 | pub mod ffi; 173 | // Rust 1.16.0 (no tests) 174 | pub mod fs; 175 | // Rust 1.16.0 (no tests, mostly, not the submodules `lazy`, `stdio`) 176 | pub mod io; 177 | // Rust 1.16.0 (no tests, missing `lookup_host` and friends) 178 | pub mod net; 179 | // Rust 1.16.0 180 | pub mod num; 181 | // Rust 1.16.0 (no tests) 182 | pub mod os; 183 | // Rust 1.16.0 184 | pub mod path; 185 | // Rust 1.16.0 (incomplete) 186 | pub mod process; 187 | pub mod thread; 188 | // Rust 1.16.0 189 | pub mod time; 190 | 191 | // Rust 1.16.0 (plus our own entry point) 192 | // The runtime entry point and a few unstable public functions used by the 193 | // compiler 194 | pub mod rt; 195 | 196 | mod ctypes; 197 | mod linux; 198 | // Rust 1.16.0 199 | mod memchr; 200 | #[cfg(not(test))] 201 | mod panicking; 202 | mod rand; 203 | mod sys; 204 | mod sys_common; 205 | mod libc; 206 | 207 | // NOTE These two are "undefined" symbols that LLVM emits but that, AFAIK, we 208 | // never use 209 | #[cfg(not(test))] 210 | #[doc(hidden)] 211 | #[no_mangle] 212 | #[unstable(feature = "steed", issue = "0")] 213 | pub unsafe extern "C" fn __aeabi_unwind_cpp_pr0() { 214 | intrinsics::unreachable() 215 | } 216 | 217 | #[cfg(not(test))] 218 | #[doc(hidden)] 219 | #[no_mangle] 220 | #[unstable(feature = "steed", issue = "0")] 221 | pub unsafe extern "C" fn __aeabi_unwind_cpp_pr1() { 222 | intrinsics::unreachable() 223 | } 224 | -------------------------------------------------------------------------------- /src/libc/internal/aarch64.rs: -------------------------------------------------------------------------------- 1 | use libc::thread; 2 | 3 | #[cfg(not(test))] 4 | mod not_test { 5 | // Syscall number is passed in x8, syscall arguments in x0, x1, x2, x3, x4. 6 | // The arguments are 7 | // (flags: c_ulong, // x0 8 | // child_stack: *mut c_void, // x1 9 | // ptid: *mut c_int, // x2 10 | // newtls: c_ulong, // x3 11 | // ctid: *mut c_int) // x4 12 | // 13 | // No registers are clobbered, x0 gets the return value. 14 | // 15 | // We do not clobber any registers, so we don't need to save any. 16 | // 17 | // The calling convention passes arguments in registers, from x0 to x6. 18 | // (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // x0 19 | // child_stack: *mut c_void, // x1 20 | // flags: c_ulong, // x2 21 | // arg: *mut c_void, // x3 22 | // ptid: *mut pid_t, // x4 23 | // newtls: *mut c_void, // x5 24 | // ctid: *mut pid_t) // x6 25 | // 26 | // Both ABIs return the function result in x0. 27 | // 28 | // This means we need the following moves: 29 | // x2 -> x0 // flags 30 | // x1 -> x1 // child_stack 31 | // x4 -> x2 // ptid 32 | // x5 -> x3 // newtls 33 | // x6 -> x4 // ctid 34 | // 35 | // We save `fn_` and `arg` on the child stack. 36 | 37 | global_asm!(" 38 | .globl __steed_clone 39 | __steed_clone: 40 | 41 | // Align the child stack. 42 | and x1,x1,#-16 43 | 44 | // Save `fn_` and `arg` on the child stack. 45 | stp x0,x3,[x1,#-16]! 46 | 47 | mov x8,#220 // CLONE 48 | mov x0,x2 // flags 49 | // child_stack 50 | mov x2,x4 // ptid 51 | mov x3,x5 // newtls 52 | mov x4,x6 // ctid 53 | svc #0 54 | 55 | cbnz x0,1f 56 | 57 | // Restore `fn_` and `arg`. 58 | ldp x1,x0,[sp],#16 59 | blr x1 60 | 61 | mov x8,#93 // EXIT 62 | // status 63 | svc #0 64 | 65 | 1: 66 | ret 67 | "); 68 | } 69 | 70 | #[inline(always)] 71 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 72 | asm!("msr tpidr_el0,$0"::"r"(thread_data)::"volatile"); 73 | } 74 | 75 | #[inline(always)] 76 | pub unsafe fn thread_self() -> *mut thread { 77 | let result; 78 | asm!("mrs $0,tpidr_el0":"=r"(result)); 79 | result 80 | } 81 | -------------------------------------------------------------------------------- /src/libc/internal/arm.rs: -------------------------------------------------------------------------------- 1 | use libc::*; 2 | use linux; 3 | 4 | #[cfg(not(test))] 5 | mod not_test { 6 | // Syscall number is passed in r7, syscall arguments in r0, r1, r2, r3, r4. 7 | // The arguments are 8 | // (flags: c_ulong, // r0 9 | // child_stack: *mut c_void, // r1 10 | // ptid: *mut c_int, // r2 11 | // newtls: c_ulong, // r3 12 | // ctid: *mut c_int) // r4 13 | // 14 | // No registers are clobbered, r0 gets the return value. 15 | // 16 | // Only r0, r1, r2, r3 are caller-saved, so we must restore the value of 17 | // all other registers before returning. 18 | // 19 | // The calling convention passes the first four arguments in r0 to r3 and 20 | // all further arguments on the stack, right to left. Since we push r4 to 21 | // r7 onto the stack in the very beginning, all stack offsets are increased 22 | // by 16. The arguments are 23 | // (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // r0 24 | // child_stack: *mut c_void, // r1 25 | // flags: c_ulong, // r2 26 | // arg: *mut c_void, // r3 27 | // ptid: *mut pid_t, // [sp,#16] 28 | // newtls: *mut c_void, // [sp,#20] 29 | // ctid: *mut pid_t) // [sp,#24] 30 | // 31 | // Both ABIs return the function result in r0. 32 | // 33 | // This means we need the following moves: 34 | // r2 -> r0 // flags 35 | // r1 -> r1 // child_stack 36 | // [sp,#16] -> r2 // ptid 37 | // [sp,#20] -> r3 // newtls 38 | // [sp,#24] -> r4 // ctid 39 | // 40 | // We save `fn_` in r5, `arg` in r6. 41 | 42 | global_asm!(" 43 | .globl __steed_clone 44 | __steed_clone: 45 | 46 | @ Save r4 to r7 47 | stmfd sp!,{r4,r5,r6,r7} 48 | 49 | mov r5,r0 @ fn_ 50 | mov r6,r3 @ arg 51 | 52 | mov r7,#120 @ CLONE 53 | mov r0,r2 @ flags 54 | @ child_stack 55 | ldr r2,[sp,#16] @ ptid 56 | ldr r3,[sp,#20] @ newtls 57 | ldr r4,[sp,#24] @ ctid 58 | 59 | and r1,r1,#-16 @ Align the stack 60 | 61 | @ Do the syscall 62 | svc 0 63 | 64 | @ CLONE returns 0 in the child thread, return if we're the parent. 65 | tst r0,r0 66 | bne 3f 67 | 68 | mov r0,r6 @ arg 69 | 70 | @ Do we need to execute `fn_` in thumb mode? 71 | tst r5,#1 72 | bne 2f 73 | 74 | @ pc (Program Counter) is always 2 instructions ahead. 75 | mov lr,pc 76 | mov pc,r5 @ fn_ 77 | 78 | @ The function will return here. 79 | __steed_clone_exit: 80 | mov r7,#1 @ EXIT 81 | @ status 82 | svc 0 83 | 84 | 2: 85 | 86 | @ Again, pc is 2 instructions ahead. 87 | mov lr,pc 88 | bx r5 @ Start thumb mode 89 | b 2b 90 | 91 | 3: 92 | 93 | @ Restore r4 to r7 94 | ldmfd sp!,{r4,r5,r6,r7} 95 | @ Return from the function. 96 | mov pc,lr 97 | "); 98 | } 99 | 100 | #[inline(always)] 101 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 102 | linux::arm_set_tls(thread_data); 103 | } 104 | 105 | #[inline(always)] 106 | pub unsafe fn thread_self() -> *mut thread { 107 | let result; 108 | asm!("mrc p15,0,$0,c13,c0,3":"=r"(result)); 109 | result 110 | } 111 | -------------------------------------------------------------------------------- /src/libc/internal/mips.rs: -------------------------------------------------------------------------------- 1 | use libc::SINGLE_THREADED_TLS; 2 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 3 | // TODO(steed, #127): Set thread-local pointer. 4 | SINGLE_THREADED_TLS = thread_data as *mut _; 5 | } 6 | -------------------------------------------------------------------------------- /src/libc/internal/mips64.rs: -------------------------------------------------------------------------------- 1 | use libc::SINGLE_THREADED_TLS; 2 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 3 | // TODO(steed, #127): Set thread-local pointer. 4 | SINGLE_THREADED_TLS = thread_data as *mut _; 5 | } 6 | -------------------------------------------------------------------------------- /src/libc/internal/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(target_arch = "aarch64")] #[path = "aarch64.rs"] mod arch; 2 | #[cfg(target_arch = "arm")] #[path = "arm.rs"] mod arch; 3 | #[cfg(target_arch = "mips")] #[path = "mips.rs"] mod arch; 4 | #[cfg(target_arch = "mips64")] #[path = "mips64.rs"] mod arch; 5 | #[cfg(target_arch = "powerpc")] #[path = "powerpc.rs"] mod arch; 6 | #[cfg(target_arch = "powerpc64")] #[path = "powerpc64.rs"] mod arch; 7 | #[cfg(target_arch = "sparc64")] #[path = "sparc64.rs"] mod arch; 8 | #[cfg(target_arch = "x86")] #[path = "x86.rs"] mod arch; 9 | #[cfg(target_arch = "x86_64")] #[path = "x86_64.rs"] mod arch; 10 | 11 | use ptr; 12 | use super::*; 13 | 14 | pub use self::arch::*; 15 | 16 | pub struct Buffer(thread); 17 | 18 | pub unsafe fn init_main_thread(buffer: *mut Buffer) { 19 | let buffer: *mut thread = &mut (*buffer).0; 20 | ptr::write(buffer, thread { 21 | this: buffer, 22 | data: thread_data::new(), 23 | }); 24 | set_thread_pointer(buffer as *mut _); 25 | } 26 | -------------------------------------------------------------------------------- /src/libc/internal/powerpc.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(test))] 2 | mod not_test { 3 | // Syscall number is passed in r0, syscall arguments in r3, r4, r5, r6, r7. 4 | // The arguments are 5 | // (flags: c_ulong, // r3 6 | // child_stack: *mut c_void, // r4 7 | // ptid: *mut c_int, // r5 8 | // newtls: c_ulong, // r6 9 | // ctid: *mut c_int) // r7 10 | // 11 | // No registers are clobbered, r3 gets the return value, the error flag 12 | // goes into r0. 13 | // 14 | // We do not clobber any registers, so we don't need to save any. 15 | // 16 | // The calling convention passes arguments int registers, from r3 to r9. 17 | // (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // r3 18 | // child_stack: *mut c_void, // r4 19 | // flags: c_ulong, // r5 20 | // arg: *mut c_void, // r6 21 | // ptid: *mut pid_t, // r7 22 | // newtls: *mut c_void, // r8 23 | // ctid: *mut pid_t) // r9 24 | // 25 | // Both ABIs return the function result in r3. 26 | // 27 | // This means we need the following moves: 28 | // r5 -> r3 // flags 29 | // r4 -> r4 // child_stack 30 | // r7 -> r5 // ptid 31 | // r8 -> r6 // newtls 32 | // r9 -> r7 // ctid 33 | // 34 | // We save `fn_` and `arg` in r30 and r31 which we need to save first. 35 | 36 | global_asm!(" 37 | .globl __steed_clone 38 | __steed_clone: 39 | 40 | # Save `fn_` and `arg` (while keeping the stack aligned). 41 | stwu 30,-16(1) 42 | stw 31,4(1) 43 | mr 30,3 # fn_ 44 | mr 31,6 # arg 45 | 46 | # Align the stack. 47 | clrrwi 4,4,4 # Store in r4, load from r4, clear last 4 bits 48 | # Mark the lowest stack frame. 49 | li 0,0 50 | stwu 0,-16(4) 51 | 52 | li 0,120 # CLONE 53 | mr 3,5 # flags 54 | # child_stack 55 | mr 5,7 # ptid 56 | mr 6,8 # newtls 57 | mr 7,9 # ctid 58 | sc 59 | 60 | # PowerPC errno post-processing 61 | bso- 1f 62 | 63 | # CLONE returns 0 in child, return if we're parent. 64 | cmpwi cr7,3,0 65 | bne cr7,2f 66 | 67 | # We're the child. 68 | mr 3,31 # arg 69 | mtctr 30 # fn_ into the ctr register 70 | bctrl # Call fn_ 71 | 72 | li 0,1 # SYS_EXIT 73 | # status 74 | sc 75 | 76 | # Parent 77 | # Negate result if error occured. 78 | 1: 79 | neg 3,3 80 | 2: 81 | 82 | # Restore saved registers 83 | lwz 30,0(1) 84 | lwz 31,4(1) 85 | addi 1,1,16 86 | 87 | blr 88 | "); 89 | } 90 | 91 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 92 | let _ = thread_data; // TODO(steed, #127): Set thread-local pointer. 93 | } 94 | -------------------------------------------------------------------------------- /src/libc/internal/powerpc64.rs: -------------------------------------------------------------------------------- 1 | use libc::SINGLE_THREADED_TLS; 2 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 3 | // TODO(steed, #127): Set thread-local pointer. 4 | SINGLE_THREADED_TLS = thread_data as *mut _; 5 | } 6 | -------------------------------------------------------------------------------- /src/libc/internal/sparc64.rs: -------------------------------------------------------------------------------- 1 | use libc::SINGLE_THREADED_TLS; 2 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 3 | // TODO(steed, #127): Set thread-local pointer. 4 | SINGLE_THREADED_TLS = thread_data as *mut _; 5 | } 6 | -------------------------------------------------------------------------------- /src/libc/internal/x86.rs: -------------------------------------------------------------------------------- 1 | use libc::*; 2 | use linux; 3 | 4 | #[cfg(not(test))] 5 | mod not_test { 6 | // Syscall number is passed in %eax, syscall arguments in %ebx, %ecx, %edx, 7 | // %esi, %edi. The arguments are 8 | // (flags: c_ulong, // %ebx 9 | // child_stack: *mut c_void, // %ecx 10 | // ptid: *mut c_int, // %edx 11 | // newtls: c_ulong, // %esi 12 | // ctid: *mut c_int) // %edi 13 | // 14 | // No registers are clobbered, %eax gets the return value. 15 | // 16 | // Only %eax, %ecx and %edx are caller-saved, so we must restore the value 17 | // of all other registers before returning. 18 | // 19 | // The cdecl calling convention passes arguments on the stack, right to 20 | // left. Since we push %ebp onto the stack in the very beginning, all 21 | // offsets are increased by 4. The arguments are 22 | // (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // 8(%ebp) 23 | // child_stack: *mut c_void, // 12(%ebp) 24 | // flags: c_ulong, // 16(%ebp) 25 | // arg: *mut c_void, // 20(%ebp) 26 | // ptid: *mut pid_t, // 24(%ebp) 27 | // newtls: *mut c_void, // 28(%ebp) 28 | // ctid: *mut pid_t) // 32(%ebp) 29 | // 30 | // Both ABIs return the function result in %eax. 31 | // 32 | // This means we need the following moves: 33 | // 16(%ebp) -> %ebx // flags 34 | // 12(%ebp) -> %ecx // child_stack 35 | // 24(%ebp) -> %edx // ptid 36 | // fancy -> %esi // newtls 37 | // 32(%ebp) -> %edi // ctid 38 | // 39 | // We need to create a struct of type `struct user_desc` (see `clone(2)` 40 | // and `set_thread_area(2)`) and store it in %esi. We do it by pushing it 41 | // onto the parent stack. 42 | // 43 | // We save `fn_` in %ebp. 44 | 45 | global_asm!(" 46 | .globl __steed_clone 47 | __steed_clone: 48 | 49 | # Stack frame 50 | push %ebp 51 | mov %esp,%ebp 52 | 53 | # Save registers 54 | push %ebx 55 | push %esi 56 | push %edi 57 | 58 | mov 12(%ebp),%ecx # child_stack 59 | and $-16,%ecx # Align the stack 60 | 61 | # Push the parameter 62 | sub $16,%ecx # Keep the stack aligned 63 | mov 20(%ebp),%edi # arg 64 | mov %edi,(%ecx) 65 | 66 | # Construct a struct of type `user_desc` 67 | 68 | # Bitfield, according to glibc: 69 | # seg_32bit:1 = 1 70 | # contents:2 = 0 71 | # read_exec_only:1 = 0 72 | # limit_in_pages:1 = 1 73 | # seg_not_present:1 = 0 74 | # useable:1 = 1 75 | push $0x51 76 | push $0xfffff # limit 77 | push 28(%ebp) # base_addr 78 | xor %eax,%eax 79 | mov %gs,%ax 80 | shr $3,%eax 81 | push %eax # entry_number 82 | 83 | mov $120,%eax # CLONE 84 | mov 16(%ebp),%ebx # flags 85 | mov 24(%ebp),%edx # ptid 86 | mov %esp,%esi # newtls 87 | mov 32(%ebp),%edi # ctid 88 | 89 | mov 8(%ebp),%ebp # fn_ 90 | 91 | int $0x80 92 | 93 | # CLONE returns 0 in the child thread, return if we're the parent. 94 | test %eax,%eax 95 | jnz 1f 96 | 97 | mov %ebp,%eax # fn_ 98 | 99 | # Mark the lowest stack frame 100 | xor %ebp,%ebp 101 | 102 | # arg is already on the stack 103 | call *%eax 104 | 105 | mov %eax,%ebx # status 106 | mov $1,%eax # EXIT 107 | int $0x80 108 | 109 | # Unreachable 110 | hlt 111 | 112 | 1: 113 | 114 | # Pop the struct 115 | add $16,%esp 116 | 117 | # Restore registers 118 | pop %edi 119 | pop %esi 120 | pop %ebx 121 | 122 | # Stack frame 123 | pop %ebp 124 | 125 | ret 126 | "); 127 | } 128 | 129 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 130 | let mut user_desc = linux::user_desc { 131 | entry_number: -1i32 as u32, 132 | base_addr: thread_data as u32, 133 | limit: 0xfffff, 134 | // This `flags` value is explained in the `asm!` block of 135 | // `__steed_clone` above. 136 | flags: 0x51, 137 | }; 138 | let result = linux::set_thread_area(&mut user_desc); 139 | if result < 0 { 140 | panic!("set_thread_pointer: set_thread_area: {}", result); 141 | } 142 | asm!("mov $0,%gs"::"r"(((user_desc.entry_number << 3) | 3) as u16)::"volatile"); 143 | } 144 | 145 | #[inline(always)] 146 | pub unsafe fn thread_self() -> *mut thread { 147 | let result; 148 | asm!("mov %gs:0,$0":"=r"(result)); 149 | result 150 | } 151 | -------------------------------------------------------------------------------- /src/libc/internal/x86_64.rs: -------------------------------------------------------------------------------- 1 | use libc::*; 2 | use linux; 3 | 4 | #[cfg(not(test))] 5 | mod not_test { 6 | // Syscall number is passed in %rax, syscall arguments in %rdi, %rsi, %rdx, 7 | // %r10, %r8. The arguments are 8 | // (flags: c_ulong, // %rdi 9 | // child_stack: *mut c_void, // %rsi 10 | // ptid: *mut c_int, // %rdx 11 | // ctid: *mut c_int // %r10 12 | // newtls: c_ulong) // %r8 13 | // 14 | // The registers %rcx and %r11 are clobbered, %rax gets the return value. 15 | // 16 | // The System V AMD64 ABI passes arguments in %rdi, %rsi, %rdx, %rcx, %r8, 17 | // %r9, 8(%rsp). The arguments are 18 | // (fn_: extern "C" fn(*mut c_void) -> *mut c_void, // %rdi 19 | // child_stack: *mut c_void, // %rsi 20 | // flags: c_ulong, // %rdx 21 | // arg: *mut c_void, // %rcx 22 | // ptid: *mut pid_t, // %r8 23 | // newtls: *mut c_void, // %r9 24 | // ctid: *mut pid_t) // 8(%rsp) 25 | // 26 | // Both ABIs return the function result in %rax. 27 | // 28 | // This means we need the following moves: 29 | // %rdx -> %rdi // flags 30 | // %rsi -> %rsi // child_stack 31 | // %r8 -> %rdx // ptid 32 | // 8(%rsp) -> %r10 // ctid 33 | // %r9 -> %r8 // newtls 34 | // 35 | // And to save `fn_`, we need 36 | // %rdi -> %r9 // fn_ 37 | // 38 | // There's a cycle in there (%rdx -> %rdi -> %r9 -> %r8 -> %rdx), we break 39 | // it at %rdi -> %r9 and move it to the scratch register %r11 instead. 40 | 41 | global_asm!(" 42 | .globl __steed_clone 43 | __steed_clone: 44 | 45 | and $-16,%rsi # Align the child stack to 16 bytes. 46 | 47 | # Push `arg` onto the child stack. 48 | sub $8,%rsi 49 | mov %rcx,(%rsi) 50 | 51 | # Temporarily store `fn_` 52 | mov %rdi,%r11 53 | 54 | mov $56,%rax # CLONE 55 | mov %rdx,%rdi # flags 56 | # child_stack 57 | mov %r8,%rdx # ptid 58 | mov 8(%rsp),%r10 # ctid 59 | mov %r9,%r8 # newtls 60 | 61 | mov %r11,%r9 # fn_ (not for the syscall) 62 | 63 | syscall 64 | 65 | # CLONE returns 0 in the child thread, return if we're the parent. 66 | test %rax,%rax 67 | jnz 1f 68 | 69 | # Mark the lowest stack frame 70 | xor %rbp,%rbp 71 | 72 | pop %rdi # arg 73 | call *%r9 # fn_ 74 | 75 | mov %rax,%rdi # status 76 | mov $60,%rax # EXIT 77 | syscall 78 | 79 | # Unreachable. 80 | hlt 81 | 82 | 1: 83 | ret 84 | "); 85 | } 86 | 87 | pub unsafe fn set_thread_pointer(thread_data: *mut ()) { 88 | let result = linux::arch_prctl(linux::ARCH_SET_FS, thread_data as c_ulong); 89 | if result < 0 { 90 | panic!("set_thread_pointer: arch_prctl: {}", result); 91 | } 92 | } 93 | 94 | #[inline(always)] 95 | pub unsafe fn thread_self() -> *mut thread { 96 | let result; 97 | asm!("mov %fs:0,$0":"=r"(result)); 98 | result 99 | } 100 | -------------------------------------------------------------------------------- /src/linux/aarch64.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0o00002000; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0o00000100; 9 | pub const O_DIRECTORY: c_int = 0o0100000; 10 | pub const O_EXCL: c_int = 0o00000200; 11 | pub const O_LARGEFILE: c_int = 0; 12 | pub const O_NONBLOCK: c_int = 0o00004000; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0o00001000; 15 | 16 | pub const FIOCLEX: c_uint = 0x5451; 17 | pub const FIONBIO: c_uint = 0x5421; 18 | 19 | // include/uapi/asm-generic/socket.h 20 | pub const SO_RCVTIMEO: c_int = 20; 21 | pub const SO_SNDTIMEO: c_int = 21; 22 | pub const SO_ERROR: c_int = 4; 23 | pub const SO_REUSEADDR: c_int = 2; 24 | pub const SO_BROADCAST: c_int = 6; 25 | 26 | pub const SIGCHLD: c_ulong = 17; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 1; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | 36 | #[derive(Clone, Copy)] 37 | #[repr(C)] 38 | pub struct stat64 { 39 | pub st_dev: dev_t, 40 | pub st_ino: ino64_t, 41 | pub st_mode: mode_t, 42 | pub st_nlink: nlink_t, 43 | pub st_uid: uid_t, 44 | pub st_gid: gid_t, 45 | pub st_rdev: dev_t, 46 | __pad1: dev_t, 47 | pub st_size: off64_t, 48 | pub st_blksize: blksize_t, 49 | __pad2: c_int, 50 | pub st_blocks: blkcnt64_t, 51 | pub st_atime: time_t, 52 | pub st_atime_nsec: c_long, 53 | pub st_mtime: time_t, 54 | pub st_mtime_nsec: c_long, 55 | pub st_ctime: time_t, 56 | pub st_ctime_nsec: c_long, 57 | __unused: [c_int; 2], 58 | } 59 | 60 | type blksize_t = i32; 61 | -------------------------------------------------------------------------------- /src/linux/arm.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0o00002000; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0o00000100; 9 | pub const O_DIRECTORY: c_int = 0o0100000; 10 | pub const O_EXCL: c_int = 0o00000200; 11 | pub const O_LARGEFILE: c_int = 0x20000; 12 | pub const O_NONBLOCK: c_int = 0o00004000; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0o00001000; 15 | 16 | pub const FIOCLEX: c_uint = 0x5451; 17 | pub const FIONBIO: c_uint = 0x5421; 18 | 19 | // include/uapi/asm-generic/socket.h 20 | pub const SO_RCVTIMEO: c_int = 20; 21 | pub const SO_SNDTIMEO: c_int = 21; 22 | pub const SO_ERROR: c_int = 4; 23 | pub const SO_REUSEADDR: c_int = 2; 24 | pub const SO_BROADCAST: c_int = 6; 25 | 26 | pub const SIGCHLD: c_ulong = 17; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 1; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | 36 | // include/linux/types.h 37 | pub type ino_t = __kernel_ino_t; 38 | // include/uapi/asm-generic/posix_types.h 39 | type __kernel_ino_t = __kernel_long_t; 40 | type __kernel_long_t = c_long; 41 | 42 | #[derive(Clone, Copy)] 43 | #[repr(C)] 44 | pub struct stat64 { 45 | pub st_dev: dev_t, 46 | __pad1: c_uint, 47 | __st_ino: ino_t, 48 | pub st_mode: mode_t, 49 | pub st_nlink: nlink_t, 50 | pub st_uid: uid_t, 51 | pub st_gid: gid_t, 52 | pub st_rdev: dev_t, 53 | __pad2: c_uint, 54 | pub st_size: off64_t, 55 | pub st_blksize: blksize_t, 56 | pub st_blocks: blkcnt64_t, 57 | pub st_atime: time_t, 58 | pub st_atime_nsec: c_long, 59 | pub st_mtime: time_t, 60 | pub st_mtime_nsec: c_long, 61 | pub st_ctime: time_t, 62 | pub st_ctime_nsec: c_long, 63 | pub st_ino: ino64_t, 64 | } 65 | 66 | pub type blksize_t = i32; 67 | 68 | // arch/arm/kernel/traps.c 69 | #[inline(always)] 70 | pub unsafe fn arm_set_tls(data: *mut ()) -> ssize_t { 71 | syscall!(ARM_SET_TLS, data) as ssize_t 72 | } 73 | -------------------------------------------------------------------------------- /src/linux/mips.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0x0008; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0x0100; 9 | pub const O_DIRECTORY: c_int = 0o00200000; 10 | pub const O_EXCL: c_int = 0x0400; 11 | pub const O_LARGEFILE: c_int = 0x2000; 12 | pub const O_NONBLOCK: c_int = 0x0080; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0x0200; 15 | 16 | pub const FIOCLEX: c_uint = 0x6601; 17 | pub const FIONBIO: c_uint = 0x667e; 18 | 19 | pub const SO_RCVTIMEO: c_int = 0x1006; 20 | pub const SO_SNDTIMEO: c_int = 0x1005; 21 | pub const SO_ERROR: c_int = 0x1007; 22 | pub const SO_REUSEADDR: c_int = 0x0004; 23 | pub const SO_BROADCAST: c_int = 0x0020; 24 | 25 | pub const SIGCHLD: c_ulong = 18; 26 | 27 | // arch/mips/include/asm/socket.h 28 | pub const SOCK_DGRAM: c_int = 1; 29 | pub const SOCK_STREAM: c_int = 2; 30 | 31 | pub const SOL_SOCKET: c_int = 0xffff; 32 | 33 | pub const MAP_ANONYMOUS: c_int = 0x0800; 34 | 35 | #[derive(Clone, Copy)] 36 | #[repr(C)] 37 | pub struct stat64 { 38 | pub st_dev: c_ulong, 39 | __st_pad1: [c_long; 3], 40 | pub st_ino: ino64_t, 41 | pub st_mode: mode_t, 42 | pub st_nlink: nlink_t, 43 | pub st_uid: uid_t, 44 | pub st_gid: gid_t, 45 | pub st_rdev: c_ulong, 46 | __st_pad2: [c_long; 2], 47 | pub st_size: off64_t, 48 | pub st_atime: time_t, 49 | pub st_atime_nsec: c_long, 50 | pub st_mtime: time_t, 51 | pub st_mtime_nsec: c_long, 52 | pub st_ctime: time_t, 53 | pub st_ctime_nsec: c_long, 54 | pub st_blksize: blksize_t, 55 | __st_pad3: c_long, 56 | pub st_blocks: blkcnt64_t, 57 | __st_pad5: [c_long; 14], 58 | } 59 | 60 | pub type blksize_t = i32; 61 | -------------------------------------------------------------------------------- /src/linux/mips64.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0x0008; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0x0100; 9 | pub const O_DIRECTORY: c_int = 0o00200000; 10 | pub const O_EXCL: c_int = 0x0400; 11 | pub const O_NONBLOCK: c_int = 0x0080; 12 | pub const O_PATH: c_int = 0o010000000; 13 | pub const O_TRUNC: c_int = 0x0200; 14 | 15 | pub const FIOCLEX: c_uint = 0x6601; 16 | pub const FIONBIO: c_uint = 0x667e; 17 | 18 | pub const SO_RCVTIMEO: c_int = 0x1006; 19 | pub const SO_SNDTIMEO: c_int = 0x1005; 20 | pub const SO_ERROR: c_int = 0x1007; 21 | pub const SO_REUSEADDR: c_int = 0x0004; 22 | pub const SO_BROADCAST: c_int = 0x0020; 23 | 24 | pub const SIGCHLD: c_ulong = 18; 25 | 26 | // arch/mips/include/asm/socket.h 27 | pub const SOCK_DGRAM: c_int = 1; 28 | pub const SOCK_STREAM: c_int = 2; 29 | 30 | pub const SOL_SOCKET: c_int = 0xffff; 31 | 32 | pub const MAP_ANONYMOUS: c_int = 0x0800; 33 | 34 | #[derive(Clone, Copy)] 35 | #[repr(C)] 36 | pub struct stat64 { 37 | pub st_dev: c_ulong, 38 | __st_pad1: [c_long; 2], 39 | pub st_ino: ino64_t, 40 | pub st_mode: mode_t, 41 | pub st_nlink: nlink_t, 42 | pub st_uid: uid_t, 43 | pub st_gid: gid_t, 44 | pub st_rdev: c_ulong, 45 | __st_pad2: [c_long; 2], 46 | pub st_size: off64_t, 47 | pub st_atime: time_t, 48 | pub st_atime_nsec: c_long, 49 | pub st_mtime: time_t, 50 | pub st_mtime_nsec: c_long, 51 | pub st_ctime: time_t, 52 | pub st_ctime_nsec: c_long, 53 | pub st_blksize: blksize_t, 54 | __st_pad3: c_long, 55 | pub st_blocks: blkcnt64_t, 56 | __st_pad5: [c_long; 7], 57 | } 58 | 59 | pub type blksize_t = i64; 60 | -------------------------------------------------------------------------------- /src/linux/powerpc.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0o00002000; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0o00000100; 9 | pub const O_DIRECTORY: c_int = 0o040000; 10 | pub const O_EXCL: c_int = 0o00000200; 11 | pub const O_LARGEFILE: c_int = 0x10000; 12 | pub const O_NONBLOCK: c_int = 0o00004000; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0o00001000; 15 | 16 | pub const FIOCLEX: c_uint = 0x20006601; 17 | pub const FIONBIO: c_uint = 0x8004667e; 18 | 19 | // include/uapi/asm-generic/socket.h 20 | pub const SO_RCVTIMEO: c_int = 18; 21 | pub const SO_SNDTIMEO: c_int = 19; 22 | pub const SO_ERROR: c_int = 4; 23 | pub const SO_REUSEADDR: c_int = 2; 24 | pub const SO_BROADCAST: c_int = 6; 25 | 26 | pub const SIGCHLD: c_ulong = 17; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 1; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | 36 | #[derive(Clone, Copy)] 37 | #[repr(C)] 38 | pub struct stat64 { 39 | pub st_dev: dev_t, 40 | pub st_ino: ino64_t, 41 | pub st_mode: mode_t, 42 | pub st_nlink: nlink_t, 43 | pub st_uid: uid_t, 44 | pub st_gid: gid_t, 45 | pub st_rdev: dev_t, 46 | __pad2: c_ushort, 47 | pub st_size: off64_t, 48 | pub st_blksize: blksize_t, 49 | pub st_blocks: blkcnt64_t, 50 | pub st_atime: time_t, 51 | pub st_atime_nsec: c_long, 52 | pub st_mtime: time_t, 53 | pub st_mtime_nsec: c_long, 54 | pub st_ctime: time_t, 55 | pub st_ctime_nsec: c_long, 56 | __glibc_reserved4: c_ulong, 57 | __glibc_reserved5: c_ulong, 58 | } 59 | 60 | pub type blksize_t = i32; 61 | -------------------------------------------------------------------------------- /src/linux/powerpc64.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0o00002000; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0o00000100; 9 | pub const O_DIRECTORY: c_int = 0o040000; 10 | pub const O_EXCL: c_int = 0o00000200; 11 | pub const O_LARGEFILE: c_int = 0; 12 | pub const O_NONBLOCK: c_int = 0o00004000; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0o00001000; 15 | 16 | pub const FIOCLEX: c_uint = 0x20006601; 17 | pub const FIONBIO: c_uint = 0x8004667e; 18 | 19 | // include/uapi/asm-generic/socket.h 20 | pub const SO_RCVTIMEO: c_int = 18; 21 | pub const SO_SNDTIMEO: c_int = 19; 22 | pub const SO_ERROR: c_int = 4; 23 | pub const SO_REUSEADDR: c_int = 2; 24 | pub const SO_BROADCAST: c_int = 6; 25 | 26 | pub const SIGCHLD: c_ulong = 17; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 1; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | 36 | #[derive(Clone, Copy)] 37 | #[repr(C)] 38 | pub struct stat64 { 39 | pub st_dev: dev_t, 40 | pub st_ino: ino64_t, 41 | pub st_nlink: nlink_t, 42 | pub st_mode: mode_t, 43 | pub st_uid: uid_t, 44 | pub st_gid: gid_t, 45 | __pad0: c_int, 46 | pub st_rdev: dev_t, 47 | pub st_size: off64_t, 48 | pub st_blksize: blksize_t, 49 | pub st_blocks: blkcnt64_t, 50 | pub st_atime: time_t, 51 | pub st_atime_nsec: c_long, 52 | pub st_mtime: time_t, 53 | pub st_mtime_nsec: c_long, 54 | pub st_ctime: time_t, 55 | pub st_ctime_nsec: c_long, 56 | __reserved: [c_long; 3], 57 | } 58 | 59 | pub type blksize_t = i64; 60 | -------------------------------------------------------------------------------- /src/linux/sparc64.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | use ctypes::c_int; 7 | 8 | pub const O_APPEND: c_int = 0x0008; 9 | pub const O_CLOEXEC: c_int = 0x400000; 10 | pub const O_CREAT: c_int = 0x0200; 11 | pub const O_DIRECTORY: c_int = 0o00200000; 12 | pub const O_EXCL: c_int = 0x0800; 13 | pub const O_NONBLOCK: c_int = 0x4000; 14 | pub const O_PATH: c_int = 0x1000000; 15 | pub const O_TRUNC: c_int = 0x0400; 16 | 17 | pub const SIGCHLD: c_ulong = 17; 18 | 19 | pub const SO_RCVTIMEO: c_int = 0x2000; 20 | pub const SO_SNDTIMEO: c_int = 0x4000; 21 | pub const SO_ERROR: c_int = 0x1007; 22 | pub const SO_REUSEADDR: c_int = 0x0004; 23 | pub const SO_BROADCAST: c_int = 0x0020; 24 | 25 | 26 | pub const FIONBIO: c_uint = 0x8004667e; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 0xffff; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | -------------------------------------------------------------------------------- /src/linux/types.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | 5 | pub use super::arch::stat64; 6 | 7 | // include/linux/types.h 8 | pub type clockid_t = __kernel_clockid_t; 9 | // pub type dev_t = __kernel_dev_t; 10 | pub type loff_t = __kernel_loff_t; 11 | pub type mode_t = __kernel_mode_t; 12 | pub type nlink_t = u32; 13 | pub type off_t = __kernel_off_t; 14 | pub type pid_t = __kernel_pid_t; 15 | pub type suseconds_t = __kernel_suseconds_t; 16 | pub type time_t = __kernel_time_t; 17 | pub type umode_t = c_ushort; 18 | 19 | // include/linux/socket.h 20 | pub type sa_family_t = __kernel_sa_family_t; 21 | // include/uapi/linux/socket.h 22 | type __kernel_sa_family_t = c_ushort; 23 | 24 | // include/uapi/asm-generic/posix_types.h 25 | type __kernel_clockid_t = c_int; 26 | // type __kernel_dev_t = u32; 27 | type __kernel_gid_t = c_uint; 28 | type __kernel_loff_t = c_longlong; 29 | type __kernel_long_t = c_long; 30 | type __kernel_mode_t = c_uint; 31 | type __kernel_off64_t = c_longlong; 32 | type __kernel_off_t = c_long; 33 | type __kernel_pid_t = c_int; 34 | type __kernel_suseconds_t = __kernel_long_t; 35 | type __kernel_time_t = __kernel_long_t; 36 | type __kernel_uid_t = c_uint; 37 | 38 | // include/uapi/linux/time.h 39 | #[derive(Clone, Copy)] 40 | #[repr(C)] 41 | pub struct timespec { 42 | pub tv_sec: time_t, 43 | pub tv_nsec: c_long, 44 | } 45 | 46 | // include/uapi/linux/time.h 47 | #[derive(Clone, Copy)] 48 | #[repr(C)] 49 | pub struct timeval { 50 | pub tv_sec: time_t, 51 | pub tv_usec: suseconds_t, 52 | } 53 | 54 | // include/linux/dirent.h 55 | #[derive(Clone, Copy)] 56 | #[repr(C)] 57 | pub struct linux_dirent64 { 58 | pub d_ino: u64, 59 | pub d_off: i64, 60 | pub d_reclen: c_ushort, 61 | pub d_type: c_uchar, 62 | pub d_name: [c_char; 0], 63 | } 64 | 65 | pub struct rusage { 66 | _unimplemented: (), 67 | } 68 | 69 | // libc helper type 70 | pub type socklen_t = c_int; 71 | 72 | // include/linux/socket.h 73 | #[repr(C)] 74 | pub struct sockaddr { 75 | pub sa_family: sa_family_t, 76 | pub sa_data: [c_char; 14], 77 | } 78 | 79 | // include/uapi/linux/in.h 80 | #[repr(C)] 81 | #[derive(Clone, Copy)] 82 | pub struct sockaddr_in { 83 | pub sin_family: sa_family_t, 84 | pub sin_port: u16, 85 | pub sin_addr: in_addr, 86 | pub pad: [u8; 8], 87 | } 88 | 89 | // include/uapi/linux/in6.h 90 | #[repr(C)] 91 | #[derive(Clone, Copy)] 92 | pub struct sockaddr_in6 { 93 | pub sin6_family: sa_family_t, 94 | pub sin6_port: u16, 95 | pub sin6_flowinfo: u32, 96 | pub sin6_addr: in6_addr, 97 | pub sin6_scope_id: u32, 98 | } 99 | 100 | // include/uapi/linux/in.h 101 | pub const UNIX_PATH_MAX: usize = 108; 102 | #[repr(C)] 103 | #[derive(Copy)] 104 | pub struct sockaddr_un { 105 | pub sun_family: sa_family_t, 106 | pub sun_path: [c_char; UNIX_PATH_MAX], 107 | } 108 | 109 | impl Clone for sockaddr_un { 110 | fn clone(&self) -> sockaddr_un { 111 | *self 112 | } 113 | } 114 | 115 | // include/uapi/linux/in.h 116 | #[repr(C)] 117 | #[derive(Clone, Copy)] 118 | pub struct in_addr { 119 | pub s_addr: u32, 120 | } 121 | 122 | // include/uapi/linux/in6.h 123 | #[repr(C)] 124 | #[derive(Clone, Copy)] 125 | pub struct in6_addr { 126 | pub s6_addr: [u8; 16], 127 | __align: [u32; 0], 128 | } 129 | 130 | // include/uapi/linux/in.h 131 | #[repr(C)] 132 | pub struct ip_mreq { 133 | pub imr_multiaddr: in_addr, 134 | pub imr_interface: in_addr, 135 | } 136 | 137 | // include/uapi/linux/in6.h 138 | #[repr(C)] 139 | pub struct ipv6_mreq { 140 | pub ipv6mr_multiaddr: in6_addr, 141 | // Changed from `c_int` to `c_uint` so it fits with the `sys::linux::net` 142 | // source. 143 | pub ipv6mr_interface: c_uint, 144 | } 145 | 146 | // include/uapi/linux/socket.h 147 | pub const _K_SS_MAXSIZE: usize = 128; 148 | pub type sockaddr_storage = __kernel_sockaddr_storage; 149 | pub struct __kernel_sockaddr_storage { 150 | pub ss_family: sa_family_t, 151 | __ss_data: [c_char; _K_SS_MAXSIZE - 2], 152 | } 153 | 154 | // Where from? 155 | pub type blkcnt64_t = i64; 156 | #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] 157 | pub type dev_t = u64; 158 | pub type gid_t = __kernel_gid_t; 159 | pub type ino64_t = c_longlong; 160 | pub type off64_t = __kernel_off64_t; 161 | pub type uid_t = __kernel_uid_t; 162 | -------------------------------------------------------------------------------- /src/linux/x86.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0o00002000; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0o00000100; 9 | pub const O_DIRECTORY: c_int = 0o00200000; 10 | pub const O_EXCL: c_int = 0o00000200; 11 | pub const O_LARGEFILE: c_int = 0x8000; 12 | pub const O_NONBLOCK: c_int = 0o00004000; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0o00001000; 15 | 16 | pub const FIOCLEX: c_uint = 0x5451; 17 | pub const FIONBIO: c_uint = 0x5421; 18 | 19 | // include/uapi/asm-generic/socket.h 20 | pub const SO_RCVTIMEO: c_int = 20; 21 | pub const SO_SNDTIMEO: c_int = 21; 22 | pub const SO_ERROR: c_int = 4; 23 | pub const SO_REUSEADDR: c_int = 2; 24 | pub const SO_BROADCAST: c_int = 6; 25 | 26 | pub const SIGCHLD: c_ulong = 17; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 1; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | 36 | // include/uapi/linux/net.h 37 | pub const SYS_SOCKET: c_ulong = 1; 38 | pub const SYS_BIND: c_ulong = 2; 39 | pub const SYS_CONNECT: c_ulong = 3; 40 | pub const SYS_LISTEN: c_ulong = 4; 41 | pub const SYS_ACCEPT: c_ulong = 5; 42 | pub const SYS_GETSOCKNAME: c_ulong = 6; 43 | pub const SYS_GETPEERNAME: c_ulong = 7; 44 | pub const SYS_SOCKETPAIR: c_ulong = 8; 45 | // pub const SYS_SEND: c_ulong = 9; 46 | // pub const SYS_RECV: c_ulong = 10; 47 | pub const SYS_SENDTO: c_ulong = 11; 48 | pub const SYS_RECVFROM: c_ulong = 12; 49 | pub const SYS_SHUTDOWN: c_ulong = 13; 50 | pub const SYS_SETSOCKOPT: c_ulong = 14; 51 | pub const SYS_GETSOCKOPT: c_ulong = 15; 52 | // pub const SYS_SENDMSG: c_ulong = 16; 53 | // pub const SYS_RECVMSG: c_ulong = 17; 54 | pub const SYS_ACCEPT4: c_ulong = 18; 55 | // pub const SYS_RECVMMSG: c_ulong = 19; 56 | // pub const SYS_SENDMMSG: c_ulong = 20; 57 | 58 | // include/linux/types.h 59 | pub type ino_t = __kernel_ino_t; 60 | // include/uapi/asm-generic/posix_types.h 61 | type __kernel_ino_t = __kernel_long_t; 62 | type __kernel_long_t = c_long; 63 | 64 | #[derive(Clone, Copy)] 65 | #[repr(C)] 66 | pub struct stat64 { 67 | pub st_dev: dev_t, 68 | __pad1: c_uint, 69 | __st_ino: ino_t, 70 | pub st_mode: mode_t, 71 | pub st_nlink: nlink_t, 72 | pub st_uid: uid_t, 73 | pub st_gid: gid_t, 74 | pub st_rdev: dev_t, 75 | __pad2: c_uint, 76 | pub st_size: off64_t, 77 | pub st_blksize: blksize_t, 78 | pub st_blocks: blkcnt64_t, 79 | pub st_atime: time_t, 80 | pub st_atime_nsec: c_long, 81 | pub st_mtime: time_t, 82 | pub st_mtime_nsec: c_long, 83 | pub st_ctime: time_t, 84 | pub st_ctime_nsec: c_long, 85 | pub st_ino: ino64_t, 86 | } 87 | 88 | pub type blksize_t = i32; 89 | 90 | #[derive(Clone, Copy)] 91 | #[repr(C)] 92 | pub struct user_desc { 93 | pub entry_number: c_uint, 94 | pub base_addr: c_uint, 95 | pub limit: c_uint, 96 | pub flags: c_uint, 97 | } 98 | 99 | // arch/x86/kernel/tls.c 100 | #[inline(always)] 101 | pub unsafe fn set_thread_area(u_info: *mut user_desc) -> ssize_t { 102 | // TODO(steed)! 103 | syscall!(SET_THREAD_AREA, u_info) as ssize_t 104 | } 105 | -------------------------------------------------------------------------------- /src/linux/x86_64.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | use ctypes::*; 4 | use linux::types::*; 5 | 6 | pub const O_APPEND: c_int = 0o00002000; 7 | pub const O_CLOEXEC: c_int = 0o02000000; 8 | pub const O_CREAT: c_int = 0o00000100; 9 | pub const O_DIRECTORY: c_int = 0o00200000; 10 | pub const O_EXCL: c_int = 0o00000200; 11 | pub const O_LARGEFILE: c_int = 0; 12 | pub const O_NONBLOCK: c_int = 0o00004000; 13 | pub const O_PATH: c_int = 0o010000000; 14 | pub const O_TRUNC: c_int = 0o00001000; 15 | 16 | pub const FIOCLEX: c_uint = 0x5451; 17 | pub const FIONBIO: c_uint = 0x5421; 18 | 19 | // include/uapi/asm-generic/socket.h 20 | pub const SO_RCVTIMEO: c_int = 20; 21 | pub const SO_SNDTIMEO: c_int = 21; 22 | pub const SO_ERROR: c_int = 4; 23 | pub const SO_REUSEADDR: c_int = 2; 24 | pub const SO_BROADCAST: c_int = 6; 25 | 26 | pub const SIGCHLD: c_ulong = 17; 27 | 28 | // include/linux/net.h 29 | pub const SOCK_STREAM: c_int = 1; 30 | pub const SOCK_DGRAM: c_int = 2; 31 | 32 | pub const SOL_SOCKET: c_int = 1; 33 | 34 | pub const MAP_ANONYMOUS: c_int = 0x20; 35 | 36 | pub type blksize_t = i64; 37 | 38 | #[derive(Clone, Copy)] 39 | #[repr(C)] 40 | pub struct stat64 { 41 | pub st_dev: dev_t, 42 | pub st_ino: ino64_t, 43 | pub st_nlink: nlink_t, 44 | pub st_mode: mode_t, 45 | pub st_uid: uid_t, 46 | pub st_gid: gid_t, 47 | __pad0: c_int, 48 | pub st_rdev: dev_t, 49 | pub st_size: off64_t, 50 | pub st_blksize: blksize_t, 51 | pub st_blocks: blkcnt64_t, 52 | pub st_atime: time_t, 53 | pub st_atime_nsec: c_long, 54 | pub st_mtime: time_t, 55 | pub st_mtime_nsec: c_long, 56 | pub st_ctime: time_t, 57 | pub st_ctime_nsec: c_long, 58 | __reserved: [c_long; 3], 59 | } 60 | 61 | // arch/x86/include/uapi/asm/prctl.h 62 | pub const ARCH_SET_FS: c_int = 0x1002; 63 | 64 | // arch/x86/um/syscall_64.c 65 | #[inline(always)] 66 | pub unsafe fn arch_prctl(code: c_int, addr: c_ulong) -> ssize_t { 67 | syscall!(ARCH_PRCTL, code, addr) as ssize_t 68 | } 69 | -------------------------------------------------------------------------------- /src/memchr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | // 11 | // Original implementation taken from rust-memchr 12 | // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch 13 | 14 | /// A safe interface to `memchr`. 15 | /// 16 | /// Returns the index corresponding to the first occurrence of `needle` in 17 | /// `haystack`, or `None` if one is not found. 18 | /// 19 | /// memchr reduces to super-optimized machine code at around an order of 20 | /// magnitude faster than `haystack.iter().position(|&b| b == needle)`. 21 | /// (See benchmarks.) 22 | /// 23 | /// # Example 24 | /// 25 | /// This shows how to find the first position of a byte in a byte string. 26 | /// 27 | /// ```rust,ignore 28 | /// use memchr::memchr; 29 | /// 30 | /// let haystack = b"the quick brown fox"; 31 | /// assert_eq!(memchr(b'k', haystack), Some(8)); 32 | /// ``` 33 | #[inline] 34 | pub fn memchr(needle: u8, haystack: &[u8]) -> Option { 35 | ::sys::memchr::memchr(needle, haystack) 36 | } 37 | 38 | /// A safe interface to `memrchr`. 39 | /// 40 | /// Returns the index corresponding to the last occurrence of `needle` in 41 | /// `haystack`, or `None` if one is not found. 42 | /// 43 | /// # Example 44 | /// 45 | /// This shows how to find the last position of a byte in a byte string. 46 | /// 47 | /// ```rust,ignore 48 | /// use memchr::memrchr; 49 | /// 50 | /// let haystack = b"the quick brown fox"; 51 | /// assert_eq!(memrchr(b'o', haystack), Some(17)); 52 | /// ``` 53 | #[inline] 54 | pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { 55 | ::sys::memchr::memrchr(needle, haystack) 56 | } 57 | 58 | #[cfg(test)] 59 | mod tests { 60 | // test the implementations for the current plattform 61 | use super::{memchr, memrchr}; 62 | 63 | #[test] 64 | fn matches_one() { 65 | assert_eq!(Some(0), memchr(b'a', b"a")); 66 | } 67 | 68 | #[test] 69 | fn matches_begin() { 70 | assert_eq!(Some(0), memchr(b'a', b"aaaa")); 71 | } 72 | 73 | #[test] 74 | fn matches_end() { 75 | assert_eq!(Some(4), memchr(b'z', b"aaaaz")); 76 | } 77 | 78 | #[test] 79 | fn matches_nul() { 80 | assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); 81 | } 82 | 83 | #[test] 84 | fn matches_past_nul() { 85 | assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); 86 | } 87 | 88 | #[test] 89 | fn no_match_empty() { 90 | assert_eq!(None, memchr(b'a', b"")); 91 | } 92 | 93 | #[test] 94 | fn no_match() { 95 | assert_eq!(None, memchr(b'a', b"xyz")); 96 | } 97 | 98 | #[test] 99 | fn matches_one_reversed() { 100 | assert_eq!(Some(0), memrchr(b'a', b"a")); 101 | } 102 | 103 | #[test] 104 | fn matches_begin_reversed() { 105 | assert_eq!(Some(3), memrchr(b'a', b"aaaa")); 106 | } 107 | 108 | #[test] 109 | fn matches_end_reversed() { 110 | assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); 111 | } 112 | 113 | #[test] 114 | fn matches_nul_reversed() { 115 | assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); 116 | } 117 | 118 | #[test] 119 | fn matches_past_nul_reversed() { 120 | assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); 121 | } 122 | 123 | #[test] 124 | fn no_match_empty_reversed() { 125 | assert_eq!(None, memrchr(b'a', b"")); 126 | } 127 | 128 | #[test] 129 | fn no_match_reversed() { 130 | assert_eq!(None, memrchr(b'a', b"xyz")); 131 | } 132 | 133 | #[test] 134 | fn each_alignment() { 135 | let mut data = [1u8; 64]; 136 | let needle = 2; 137 | let pos = 40; 138 | data[pos] = needle; 139 | for start in 0..16 { 140 | assert_eq!(Some(pos - start), memchr(needle, &data[start..])); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/net/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Networking primitives for TCP/UDP communication. 12 | 13 | #![stable(feature = "rust1", since = "1.0.0")] 14 | 15 | #[cfg(issue = "101")] 16 | use fmt; 17 | use io::{self, Error, ErrorKind}; 18 | #[cfg(issue = "101")] 19 | use sys_common::net as net_imp; 20 | 21 | #[stable(feature = "rust1", since = "1.0.0")] 22 | pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; 23 | #[stable(feature = "rust1", since = "1.0.0")] 24 | pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; 25 | #[stable(feature = "rust1", since = "1.0.0")] 26 | pub use self::tcp::{TcpStream, TcpListener, Incoming}; 27 | #[stable(feature = "rust1", since = "1.0.0")] 28 | pub use self::udp::UdpSocket; 29 | #[stable(feature = "rust1", since = "1.0.0")] 30 | pub use self::parser::AddrParseError; 31 | 32 | mod ip; 33 | mod addr; 34 | mod tcp; 35 | mod udp; 36 | mod parser; 37 | #[cfg(test)] 38 | #[cfg(issue = "115")] 39 | mod test; 40 | 41 | /// Possible values which can be passed to the [`shutdown`] method of 42 | /// [`TcpStream`]. 43 | /// 44 | /// [`shutdown`]: struct.TcpStream.html#method.shutdown 45 | /// [`TcpStream`]: struct.TcpStream.html 46 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 47 | #[stable(feature = "rust1", since = "1.0.0")] 48 | pub enum Shutdown { 49 | /// Indicates that the reading portion of this stream/socket should be shut 50 | /// down. All currently blocked and future reads will return `Ok(0)`. 51 | #[stable(feature = "rust1", since = "1.0.0")] 52 | Read, 53 | /// Indicates that the writing portion of this stream/socket should be shut 54 | /// down. All currently blocked and future writes will return an error. 55 | #[stable(feature = "rust1", since = "1.0.0")] 56 | Write, 57 | /// Shut down both the reading and writing portions of this stream. 58 | /// 59 | /// See `Shutdown::Read` and `Shutdown::Write` for more information. 60 | #[stable(feature = "rust1", since = "1.0.0")] 61 | Both, 62 | } 63 | 64 | #[doc(hidden)] 65 | trait NetInt { 66 | fn from_be(i: Self) -> Self; 67 | fn to_be(&self) -> Self; 68 | } 69 | macro_rules! doit { 70 | ($($t:ident)*) => ($(impl NetInt for $t { 71 | fn from_be(i: Self) -> Self { <$t>::from_be(i) } 72 | fn to_be(&self) -> Self { <$t>::to_be(*self) } 73 | })*) 74 | } 75 | doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } 76 | 77 | fn hton(i: I) -> I { i.to_be() } 78 | fn ntoh(i: I) -> I { I::from_be(i) } 79 | 80 | fn each_addr(addr: A, mut f: F) -> io::Result 81 | where F: FnMut(&SocketAddr) -> io::Result 82 | { 83 | let mut last_err = None; 84 | for addr in addr.to_socket_addrs()? { 85 | match f(&addr) { 86 | Ok(l) => return Ok(l), 87 | Err(e) => last_err = Some(e), 88 | } 89 | } 90 | Err(last_err.unwrap_or_else(|| { 91 | Error::new(ErrorKind::InvalidInput, 92 | "could not resolve to any addresses") 93 | })) 94 | } 95 | 96 | /// An iterator over `SocketAddr` values returned from a host lookup operation. 97 | #[unstable(feature = "lookup_host", reason = "unsure about the returned \ 98 | iterator and returning socket \ 99 | addresses", 100 | issue = "27705")] 101 | #[cfg(issue = "101")] 102 | pub struct LookupHost(net_imp::LookupHost); 103 | 104 | #[unstable(feature = "lookup_host", reason = "unsure about the returned \ 105 | iterator and returning socket \ 106 | addresses", 107 | issue = "27705")] 108 | #[cfg(issue = "101")] 109 | impl Iterator for LookupHost { 110 | type Item = SocketAddr; 111 | fn next(&mut self) -> Option { self.0.next() } 112 | } 113 | 114 | #[stable(feature = "std_debug", since = "1.15.0")] 115 | #[cfg(issue = "101")] 116 | impl fmt::Debug for LookupHost { 117 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 118 | f.pad("LookupHost { .. }") 119 | } 120 | } 121 | 122 | /// Resolve the host specified by `host` as a number of `SocketAddr` instances. 123 | /// 124 | /// This method may perform a DNS query to resolve `host` and may also inspect 125 | /// system configuration to resolve the specified hostname. 126 | /// 127 | /// The returned iterator will skip over any unknown addresses returned by the 128 | /// operating system. 129 | /// 130 | /// # Examples 131 | /// 132 | /// ```no_run 133 | /// #![feature(lookup_host)] 134 | /// 135 | /// use std::net; 136 | /// 137 | /// # fn foo() -> std::io::Result<()> { 138 | /// for host in net::lookup_host("rust-lang.org")? { 139 | /// println!("found address: {}", host); 140 | /// } 141 | /// # Ok(()) 142 | /// # } 143 | /// ``` 144 | #[unstable(feature = "lookup_host", reason = "unsure about the returned \ 145 | iterator and returning socket \ 146 | addresses", 147 | issue = "27705")] 148 | #[cfg(issue = "101")] 149 | pub fn lookup_host(host: &str) -> io::Result { 150 | net_imp::lookup_host(host).map(LookupHost) 151 | } 152 | -------------------------------------------------------------------------------- /src/net/test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![allow(warnings)] // not used on emscripten 12 | 13 | use env; 14 | use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr, ToSocketAddrs}; 15 | use sync::atomic::{AtomicUsize, Ordering}; 16 | 17 | static PORT: AtomicUsize = AtomicUsize::new(0); 18 | 19 | pub fn next_test_ip4() -> SocketAddr { 20 | let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); 21 | SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)) 22 | } 23 | 24 | pub fn next_test_ip6() -> SocketAddr { 25 | let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); 26 | SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 27 | port, 0, 0)) 28 | } 29 | 30 | pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { 31 | SocketAddr::V4(SocketAddrV4::new(a, p)) 32 | } 33 | 34 | pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { 35 | SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) 36 | } 37 | 38 | pub fn tsa(a: A) -> Result, String> { 39 | match a.to_socket_addrs() { 40 | Ok(a) => Ok(a.collect()), 41 | Err(e) => Err(e.to_string()), 42 | } 43 | } 44 | 45 | // The bots run multiple builds at the same time, and these builds 46 | // all want to use ports. This function figures out which workspace 47 | // it is running in and assigns a port range based on it. 48 | fn base_port() -> u16 { 49 | let cwd = env::current_dir().unwrap(); 50 | let dirs = ["32-opt", "32-nopt", 51 | "musl-64-opt", "cross-opt", 52 | "64-opt", "64-nopt", "64-opt-vg", "64-debug-opt", 53 | "all-opt", "snap3", "dist"]; 54 | dirs.iter().enumerate().find(|&(_, dir)| { 55 | cwd.to_str().unwrap().contains(dir) 56 | }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600 57 | } 58 | -------------------------------------------------------------------------------- /src/os/linux/fs.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![stable(feature = "metadata_ext", since = "1.1.0")] 12 | 13 | use libc; 14 | 15 | use fs::Metadata; 16 | use sys_common::AsInner; 17 | 18 | #[allow(deprecated)] 19 | use os::linux::raw; 20 | 21 | /// OS-specific extension methods for `fs::Metadata` 22 | #[stable(feature = "metadata_ext", since = "1.1.0")] 23 | pub trait MetadataExt { 24 | /// Gain a reference to the underlying `stat` structure which contains 25 | /// the raw information returned by the OS. 26 | /// 27 | /// The contents of the returned `stat` are **not** consistent across 28 | /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the 29 | /// cross-Unix abstractions contained within the raw stat. 30 | #[stable(feature = "metadata_ext", since = "1.1.0")] 31 | #[rustc_deprecated(since = "1.8.0", 32 | reason = "deprecated in favor of the accessor \ 33 | methods of this trait")] 34 | #[allow(deprecated)] 35 | fn as_raw_stat(&self) -> &raw::stat; 36 | 37 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 38 | fn st_dev(&self) -> u64; 39 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 40 | fn st_ino(&self) -> u64; 41 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 42 | fn st_mode(&self) -> u32; 43 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 44 | fn st_nlink(&self) -> u64; 45 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 46 | fn st_uid(&self) -> u32; 47 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 48 | fn st_gid(&self) -> u32; 49 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 50 | fn st_rdev(&self) -> u64; 51 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 52 | fn st_size(&self) -> u64; 53 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 54 | fn st_atime(&self) -> i64; 55 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 56 | fn st_atime_nsec(&self) -> i64; 57 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 58 | fn st_mtime(&self) -> i64; 59 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 60 | fn st_mtime_nsec(&self) -> i64; 61 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 62 | fn st_ctime(&self) -> i64; 63 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 64 | fn st_ctime_nsec(&self) -> i64; 65 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 66 | fn st_blksize(&self) -> u64; 67 | #[stable(feature = "metadata_ext2", since = "1.8.0")] 68 | fn st_blocks(&self) -> u64; 69 | } 70 | 71 | #[stable(feature = "metadata_ext", since = "1.1.0")] 72 | impl MetadataExt for Metadata { 73 | #[allow(deprecated)] 74 | fn as_raw_stat(&self) -> &raw::stat { 75 | unsafe { 76 | &*(self.as_inner().as_inner() as *const libc::stat64 77 | as *const raw::stat) 78 | } 79 | } 80 | fn st_dev(&self) -> u64 { 81 | self.as_inner().as_inner().st_dev as u64 82 | } 83 | fn st_ino(&self) -> u64 { 84 | self.as_inner().as_inner().st_ino as u64 85 | } 86 | fn st_mode(&self) -> u32 { 87 | self.as_inner().as_inner().st_mode as u32 88 | } 89 | fn st_nlink(&self) -> u64 { 90 | self.as_inner().as_inner().st_nlink as u64 91 | } 92 | fn st_uid(&self) -> u32 { 93 | self.as_inner().as_inner().st_uid as u32 94 | } 95 | fn st_gid(&self) -> u32 { 96 | self.as_inner().as_inner().st_gid as u32 97 | } 98 | fn st_rdev(&self) -> u64 { 99 | self.as_inner().as_inner().st_rdev as u64 100 | } 101 | fn st_size(&self) -> u64 { 102 | self.as_inner().as_inner().st_size as u64 103 | } 104 | fn st_atime(&self) -> i64 { 105 | self.as_inner().as_inner().st_atime as i64 106 | } 107 | fn st_atime_nsec(&self) -> i64 { 108 | self.as_inner().as_inner().st_atime_nsec as i64 109 | } 110 | fn st_mtime(&self) -> i64 { 111 | self.as_inner().as_inner().st_mtime as i64 112 | } 113 | fn st_mtime_nsec(&self) -> i64 { 114 | self.as_inner().as_inner().st_mtime_nsec as i64 115 | } 116 | fn st_ctime(&self) -> i64 { 117 | self.as_inner().as_inner().st_ctime as i64 118 | } 119 | fn st_ctime_nsec(&self) -> i64 { 120 | self.as_inner().as_inner().st_ctime_nsec as i64 121 | } 122 | fn st_blksize(&self) -> u64 { 123 | self.as_inner().as_inner().st_blksize as u64 124 | } 125 | fn st_blocks(&self) -> u64 { 126 | self.as_inner().as_inner().st_blocks as u64 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/os/linux/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Linux-specific definitions 12 | 13 | #![stable(feature = "raw_ext", since = "1.1.0")] 14 | 15 | pub mod raw; 16 | pub mod fs; 17 | -------------------------------------------------------------------------------- /src/os/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! OS-specific functionality. 12 | 13 | #![stable(feature = "os", since = "1.0.0")] 14 | #![allow(missing_docs, bad_style, missing_debug_implementations)] 15 | 16 | #[cfg(any(target_os = "redox", unix))] 17 | #[stable(feature = "rust1", since = "1.0.0")] 18 | pub use sys::ext as unix; 19 | #[cfg(windows)] 20 | #[stable(feature = "rust1", since = "1.0.0")] 21 | pub use sys::ext as windows; 22 | 23 | #[cfg(target_os = "android")] pub mod android; 24 | #[cfg(target_os = "bitrig")] pub mod bitrig; 25 | #[cfg(target_os = "dragonfly")] pub mod dragonfly; 26 | #[cfg(target_os = "freebsd")] pub mod freebsd; 27 | #[cfg(target_os = "haiku")] pub mod haiku; 28 | #[cfg(target_os = "ios")] pub mod ios; 29 | #[cfg(target_os = "linux")] pub mod linux; 30 | #[cfg(target_os = "macos")] pub mod macos; 31 | #[cfg(target_os = "nacl")] pub mod nacl; 32 | #[cfg(target_os = "netbsd")] pub mod netbsd; 33 | #[cfg(target_os = "openbsd")] pub mod openbsd; 34 | #[cfg(target_os = "solaris")] pub mod solaris; 35 | #[cfg(target_os = "emscripten")] pub mod emscripten; 36 | #[cfg(target_os = "fuchsia")] pub mod fuchsia; 37 | 38 | pub mod raw; 39 | -------------------------------------------------------------------------------- /src/os/raw.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Raw OS-specific types for the current platform/architecture 12 | 13 | #![stable(feature = "raw_os", since = "1.1.0")] 14 | 15 | use fmt; 16 | 17 | #[cfg(any(target_os = "emscripten", 18 | all(target_os = "linux", any(target_arch = "aarch64", 19 | target_arch = "arm", 20 | target_arch = "powerpc", 21 | target_arch = "powerpc64", 22 | target_arch = "s390x")), 23 | all(target_os = "android", any(target_arch = "aarch64", 24 | target_arch = "arm")), 25 | all(target_os = "fuchsia", target_arch = "aarch64")))] 26 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; 27 | #[cfg(not(any(target_os = "emscripten", 28 | all(target_os = "linux", any(target_arch = "aarch64", 29 | target_arch = "arm", 30 | target_arch = "powerpc", 31 | target_arch = "powerpc64", 32 | target_arch = "s390x")), 33 | all(target_os = "android", any(target_arch = "aarch64", 34 | target_arch = "arm")), 35 | all(target_os = "fuchsia", target_arch = "aarch64"))))] 36 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; 37 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; 38 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; 39 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16; 40 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16; 41 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32; 42 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32; 43 | #[cfg(any(target_pointer_width = "32", windows))] 44 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32; 45 | #[cfg(any(target_pointer_width = "32", windows))] 46 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32; 47 | #[cfg(all(target_pointer_width = "64", not(windows)))] 48 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64; 49 | #[cfg(all(target_pointer_width = "64", not(windows)))] 50 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64; 51 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64; 52 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64; 53 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32; 54 | #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; 55 | 56 | /// Type used to construct void pointers for use with C. 57 | /// 58 | /// This type is only useful as a pointer target. Do not use it as a 59 | /// return type for FFI functions which have the `void` return type in 60 | /// C. Use the unit type `()` or omit the return type instead. 61 | // NB: For LLVM to recognize the void pointer type and by extension 62 | // functions like malloc(), we need to have it represented as i8* in 63 | // LLVM bitcode. The enum used here ensures this and prevents misuse 64 | // of the "raw" type by only having private variants.. We need two 65 | // variants, because the compiler complains about the repr attribute 66 | // otherwise. 67 | #[repr(u8)] 68 | #[stable(feature = "raw_os", since = "1.1.0")] 69 | pub enum c_void { 70 | #[unstable(feature = "c_void_variant", reason = "should not have to exist", 71 | issue = "0")] 72 | #[doc(hidden)] __variant1, 73 | #[unstable(feature = "c_void_variant", reason = "should not have to exist", 74 | issue = "0")] 75 | #[doc(hidden)] __variant2, 76 | } 77 | 78 | #[stable(feature = "std_debug", since = "1.16.0")] 79 | impl fmt::Debug for c_void { 80 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 81 | f.pad("c_void") 82 | } 83 | } 84 | 85 | #[cfg(test)] 86 | #[allow(unused_imports)] 87 | mod tests { 88 | use any::TypeId; 89 | use libc; 90 | use mem; 91 | 92 | macro_rules! ok { 93 | ($($t:ident)*) => {$( 94 | assert!(TypeId::of::() == TypeId::of::(), 95 | "{} is wrong", stringify!($t)); 96 | )*} 97 | } 98 | 99 | #[test] 100 | fn same() { 101 | use os::raw; 102 | ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong 103 | c_longlong c_ulonglong c_float c_double); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/panicking.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use io::Write; 3 | 4 | use {io, process}; 5 | 6 | #[lang = "panic_fmt"] 7 | pub extern "C" fn rust_begin_panic(msg: fmt::Arguments, 8 | file: &'static str, 9 | line: u32) 10 | -> ! { 11 | let mut stderr = io::stderr(); 12 | stderr.write_all(b"panicked at '") 13 | .ok() 14 | .and_then(|_| stderr.write_fmt(msg).ok()) 15 | .and_then(|_| writeln!(stderr, "', {}:{}", file, line).ok()); 16 | 17 | process::exit(101) 18 | } 19 | -------------------------------------------------------------------------------- /src/prelude/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The Rust Prelude. 12 | //! 13 | //! Rust comes with a variety of things in its standard library. However, if 14 | //! you had to manually import every single thing that you used, it would be 15 | //! very verbose. But importing a lot of things that a program never uses isn't 16 | //! good either. A balance needs to be struck. 17 | //! 18 | //! The *prelude* is the list of things that Rust automatically imports into 19 | //! every Rust program. It's kept as small as possible, and is focused on 20 | //! things, particularly traits, which are used in almost every single Rust 21 | //! program. 22 | //! 23 | //! On a technical level, Rust inserts 24 | //! 25 | //! ```ignore 26 | //! extern crate std; 27 | //! ``` 28 | //! 29 | //! into the crate root of every crate, and 30 | //! 31 | //! ```ignore 32 | //! use std::prelude::v1::*; 33 | //! ``` 34 | //! 35 | //! into every module. 36 | //! 37 | //! # Other preludes 38 | //! 39 | //! Preludes can be seen as a pattern to make using multiple types more 40 | //! convenient. As such, you'll find other preludes in the standard library, 41 | //! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may 42 | //! also define their own preludes. 43 | //! 44 | //! [`std::io::prelude`]: ../io/prelude/index.html 45 | //! 46 | //! The difference between 'the prelude' and these other preludes is that they 47 | //! are not automatically `use`'d, and must be imported manually. This is still 48 | //! easier than importing all of their constituent components. 49 | //! 50 | //! # Prelude contents 51 | //! 52 | //! The current version of the prelude (version 1) lives in 53 | //! [`std::prelude::v1`], and reexports the following. 54 | //! 55 | //! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker 56 | //! traits indicate fundamental properties of types. 57 | //! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various 58 | //! operations for both destructors and overloading `()`. 59 | //! * [`std::mem`]::[`drop`], a convenience function for explicitly dropping a 60 | //! value. 61 | //! * [`std::boxed`]::[`Box`], a way to allocate values on the heap. 62 | //! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines 63 | //! [`to_owned()`], the generic method for creating an owned type from a 64 | //! borrowed type. 65 | //! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`], 66 | //! the method for producing a copy of a value. 67 | //! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The 68 | //! comparison traits, which implement the comparison operators and are often 69 | //! seen in trait bounds. 70 | //! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic 71 | //! conversions, used by savvy API authors to create overloaded methods. 72 | //! * [`std::default`]::[`Default`], types that have default values. 73 | //! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`], 74 | //! [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various 75 | //! kinds. 76 | //! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which 77 | //! expresses the presence or absence of a value. This type is so commonly 78 | //! used, its variants are also exported. 79 | //! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions 80 | //! that may succeed or fail. Like [`Option`], its variants are exported as 81 | //! well. 82 | //! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical 83 | //! reasons, but shouldn't have to exist. It provides a few useful methods on 84 | //! slices. 85 | //! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings. 86 | //! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated 87 | //! vector. 88 | //! 89 | //! [`AsMut`]: ../convert/trait.AsMut.html 90 | //! [`AsRef`]: ../convert/trait.AsRef.html 91 | //! [`Box`]: ../boxed/struct.Box.html 92 | //! [`Clone`]: ../clone/trait.Clone.html 93 | //! [`Copy`]: ../marker/trait.Copy.html 94 | //! [`Default`]: ../default/trait.Default.html 95 | //! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html 96 | //! [`Drop`]: ../ops/trait.Drop.html 97 | //! [`Eq`]: ../cmp/trait.Eq.html 98 | //! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html 99 | //! [`Extend`]: ../iter/trait.Extend.html 100 | //! [`FnMut`]: ../ops/trait.FnMut.html 101 | //! [`FnOnce`]: ../ops/trait.FnOnce.html 102 | //! [`Fn`]: ../ops/trait.Fn.html 103 | //! [`From`]: ../convert/trait.From.html 104 | //! [`IntoIterator`]: ../iter/trait.IntoIterator.html 105 | //! [`Into`]: ../convert/trait.Into.html 106 | //! [`Iterator`]: ../iter/trait.Iterator.html 107 | //! [`Option`]: ../option/enum.Option.html 108 | //! [`Ord`]: ../cmp/trait.Ord.html 109 | //! [`PartialEq`]: ../cmp/trait.PartialEq.html 110 | //! [`PartialOrd`]: ../cmp/trait.PartialOrd.html 111 | //! [`Result`]: ../result/enum.Result.html 112 | //! [`Send`]: ../marker/trait.Send.html 113 | //! [`Sized`]: ../marker/trait.Sized.html 114 | //! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html 115 | //! [`String`]: ../string/struct.String.html 116 | //! [`Sync`]: ../marker/trait.Sync.html 117 | //! [`ToOwned`]: ../borrow/trait.ToOwned.html 118 | //! [`ToString`]: ../string/trait.ToString.html 119 | //! [`Vec`]: ../vec/struct.Vec.html 120 | //! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone 121 | //! [`drop`]: ../mem/fn.drop.html 122 | //! [`std::borrow`]: ../borrow/index.html 123 | //! [`std::boxed`]: ../boxed/index.html 124 | //! [`std::clone`]: ../clone/index.html 125 | //! [`std::cmp`]: ../cmp/index.html 126 | //! [`std::convert`]: ../convert/index.html 127 | //! [`std::default`]: ../default/index.html 128 | //! [`std::iter`]: ../iter/index.html 129 | //! [`std::marker`]: ../marker/index.html 130 | //! [`std::mem`]: ../mem/index.html 131 | //! [`std::ops`]: ../ops/index.html 132 | //! [`std::option`]: ../option/index.html 133 | //! [`std::prelude::v1`]: v1/index.html 134 | //! [`std::result`]: ../result/index.html 135 | //! [`std::slice`]: ../slice/index.html 136 | //! [`std::string`]: ../string/index.html 137 | //! [`std::vec`]: ../vec/index.html 138 | //! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned 139 | //! [book-closures]: ../../book/closures.html 140 | //! [book-dtor]: ../../book/drop.html 141 | //! [book-enums]: ../../book/enums.html 142 | //! [book-iter]: ../../book/iterators.html 143 | 144 | #![stable(feature = "rust1", since = "1.0.0")] 145 | 146 | pub mod v1; 147 | -------------------------------------------------------------------------------- /src/prelude/v1.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The first version of the prelude of The Rust Standard Library. 12 | //! 13 | //! See the [module-level documentation](../index.html) for more. 14 | 15 | #![stable(feature = "rust1", since = "1.0.0")] 16 | 17 | // Reexported core operators 18 | #[stable(feature = "rust1", since = "1.0.0")] 19 | #[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync}; 20 | #[stable(feature = "rust1", since = "1.0.0")] 21 | #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce}; 22 | 23 | // Reexported functions 24 | #[stable(feature = "rust1", since = "1.0.0")] 25 | #[doc(no_inline)] pub use mem::drop; 26 | 27 | // Reexported types and traits 28 | #[stable(feature = "rust1", since = "1.0.0")] 29 | #[doc(no_inline)] pub use boxed::Box; 30 | #[stable(feature = "rust1", since = "1.0.0")] 31 | #[doc(no_inline)] pub use borrow::ToOwned; 32 | #[stable(feature = "rust1", since = "1.0.0")] 33 | #[doc(no_inline)] pub use clone::Clone; 34 | #[stable(feature = "rust1", since = "1.0.0")] 35 | #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; 36 | #[stable(feature = "rust1", since = "1.0.0")] 37 | #[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; 38 | #[stable(feature = "rust1", since = "1.0.0")] 39 | #[doc(no_inline)] pub use default::Default; 40 | #[stable(feature = "rust1", since = "1.0.0")] 41 | #[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator}; 42 | #[stable(feature = "rust1", since = "1.0.0")] 43 | #[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator}; 44 | #[stable(feature = "rust1", since = "1.0.0")] 45 | #[doc(no_inline)] pub use option::Option::{self, Some, None}; 46 | #[stable(feature = "rust1", since = "1.0.0")] 47 | #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; 48 | #[stable(feature = "rust1", since = "1.0.0")] 49 | #[doc(no_inline)] pub use slice::SliceConcatExt; 50 | #[stable(feature = "rust1", since = "1.0.0")] 51 | #[doc(no_inline)] pub use string::{String, ToString}; 52 | #[stable(feature = "rust1", since = "1.0.0")] 53 | #[doc(no_inline)] pub use vec::Vec; 54 | -------------------------------------------------------------------------------- /src/rand/reader.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! A wrapper around any Read to treat it as an RNG. 12 | 13 | #![allow(dead_code)] 14 | 15 | use io::prelude::*; 16 | use rand::Rng; 17 | 18 | /// An RNG that reads random bytes straight from a `Read`. This will 19 | /// work best with an infinite reader, but this is not required. 20 | /// 21 | /// # Panics 22 | /// 23 | /// It will panic if it there is insufficient data to fulfill a request. 24 | pub struct ReaderRng { 25 | reader: R 26 | } 27 | 28 | impl ReaderRng { 29 | /// Create a new `ReaderRng` from a `Read`. 30 | pub fn new(r: R) -> ReaderRng { 31 | ReaderRng { 32 | reader: r 33 | } 34 | } 35 | } 36 | 37 | impl Rng for ReaderRng { 38 | fn next_u32(&mut self) -> u32 { 39 | // This is designed for speed: reading a LE integer on a LE 40 | // platform just involves blitting the bytes into the memory 41 | // of the u32, similarly for BE on BE; avoiding byteswapping. 42 | let mut bytes = [0; 4]; 43 | self.fill_bytes(&mut bytes); 44 | unsafe { *(bytes.as_ptr() as *const u32) } 45 | } 46 | fn next_u64(&mut self) -> u64 { 47 | // see above for explanation. 48 | let mut bytes = [0; 8]; 49 | self.fill_bytes(&mut bytes); 50 | unsafe { *(bytes.as_ptr() as *const u64) } 51 | } 52 | fn fill_bytes(&mut self, mut v: &mut [u8]) { 53 | while !v.is_empty() { 54 | let t = v; 55 | match self.reader.read(t) { 56 | Ok(0) => panic!("ReaderRng.fill_bytes: EOF reached"), 57 | Ok(n) => v = t.split_at_mut(n).1, 58 | Err(e) => panic!("ReaderRng.fill_bytes: {}", e), 59 | } 60 | } 61 | } 62 | } 63 | 64 | #[cfg(test)] 65 | mod tests { 66 | use super::ReaderRng; 67 | use rand::Rng; 68 | 69 | #[test] 70 | fn test_reader_rng_u64() { 71 | // transmute from the target to avoid endianness concerns. 72 | let v = &[0, 0, 0, 0, 0, 0, 0, 1, 73 | 0, 0, 0, 0, 0, 0, 0, 2, 74 | 0, 0, 0, 0, 0, 0, 0, 3][..]; 75 | let mut rng = ReaderRng::new(v); 76 | 77 | assert_eq!(rng.next_u64(), 1u64.to_be()); 78 | assert_eq!(rng.next_u64(), 2u64.to_be()); 79 | assert_eq!(rng.next_u64(), 3u64.to_be()); 80 | } 81 | #[test] 82 | fn test_reader_rng_u32() { 83 | let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..]; 84 | let mut rng = ReaderRng::new(v); 85 | 86 | assert_eq!(rng.next_u32(), 1u32.to_be()); 87 | assert_eq!(rng.next_u32(), 2u32.to_be()); 88 | assert_eq!(rng.next_u32(), 3u32.to_be()); 89 | } 90 | #[test] 91 | fn test_reader_rng_fill_bytes() { 92 | let v = [1, 2, 3, 4, 5, 6, 7, 8]; 93 | let mut w = [0; 8]; 94 | 95 | let mut rng = ReaderRng::new(&v[..]); 96 | rng.fill_bytes(&mut w); 97 | 98 | assert!(v == w); 99 | } 100 | 101 | #[test] 102 | #[should_panic] 103 | fn test_reader_rng_insufficient_bytes() { 104 | let mut rng = ReaderRng::new(&[][..]); 105 | let mut v = [0; 3]; 106 | rng.fill_bytes(&mut v); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/sync/mod.rs: -------------------------------------------------------------------------------- 1 | #![stable(feature = "steed", since = "1.0.0")] 2 | 3 | #[stable(feature = "steed", since = "1.0.0")] 4 | pub use alloc::arc::{Arc, Weak}; 5 | #[stable(feature = "steed", since = "1.0.0")] 6 | pub use core::sync::atomic; 7 | #[stable(feature = "steed", since = "1.0.0")] 8 | pub use self::mutex::{Mutex, MutexGuard}; 9 | 10 | mod mutex; 11 | -------------------------------------------------------------------------------- /src/sys/linux/env.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #[cfg(target_os = "linux")] 12 | pub mod os { 13 | pub const FAMILY: &'static str = "unix"; 14 | pub const OS: &'static str = "linux"; 15 | pub const DLL_PREFIX: &'static str = "lib"; 16 | pub const DLL_SUFFIX: &'static str = ".so"; 17 | pub const DLL_EXTENSION: &'static str = "so"; 18 | pub const EXE_SUFFIX: &'static str = ""; 19 | pub const EXE_EXTENSION: &'static str = ""; 20 | } 21 | 22 | #[cfg(target_os = "macos")] 23 | pub mod os { 24 | pub const FAMILY: &'static str = "unix"; 25 | pub const OS: &'static str = "macos"; 26 | pub const DLL_PREFIX: &'static str = "lib"; 27 | pub const DLL_SUFFIX: &'static str = ".dylib"; 28 | pub const DLL_EXTENSION: &'static str = "dylib"; 29 | pub const EXE_SUFFIX: &'static str = ""; 30 | pub const EXE_EXTENSION: &'static str = ""; 31 | } 32 | 33 | #[cfg(target_os = "ios")] 34 | pub mod os { 35 | pub const FAMILY: &'static str = "unix"; 36 | pub const OS: &'static str = "ios"; 37 | pub const DLL_PREFIX: &'static str = "lib"; 38 | pub const DLL_SUFFIX: &'static str = ".dylib"; 39 | pub const DLL_EXTENSION: &'static str = "dylib"; 40 | pub const EXE_SUFFIX: &'static str = ""; 41 | pub const EXE_EXTENSION: &'static str = ""; 42 | } 43 | 44 | #[cfg(target_os = "freebsd")] 45 | pub mod os { 46 | pub const FAMILY: &'static str = "unix"; 47 | pub const OS: &'static str = "freebsd"; 48 | pub const DLL_PREFIX: &'static str = "lib"; 49 | pub const DLL_SUFFIX: &'static str = ".so"; 50 | pub const DLL_EXTENSION: &'static str = "so"; 51 | pub const EXE_SUFFIX: &'static str = ""; 52 | pub const EXE_EXTENSION: &'static str = ""; 53 | } 54 | 55 | #[cfg(target_os = "dragonfly")] 56 | pub mod os { 57 | pub const FAMILY: &'static str = "unix"; 58 | pub const OS: &'static str = "dragonfly"; 59 | pub const DLL_PREFIX: &'static str = "lib"; 60 | pub const DLL_SUFFIX: &'static str = ".so"; 61 | pub const DLL_EXTENSION: &'static str = "so"; 62 | pub const EXE_SUFFIX: &'static str = ""; 63 | pub const EXE_EXTENSION: &'static str = ""; 64 | } 65 | 66 | #[cfg(target_os = "bitrig")] 67 | pub mod os { 68 | pub const FAMILY: &'static str = "unix"; 69 | pub const OS: &'static str = "bitrig"; 70 | pub const DLL_PREFIX: &'static str = "lib"; 71 | pub const DLL_SUFFIX: &'static str = ".so"; 72 | pub const DLL_EXTENSION: &'static str = "so"; 73 | pub const EXE_SUFFIX: &'static str = ""; 74 | pub const EXE_EXTENSION: &'static str = ""; 75 | } 76 | 77 | #[cfg(target_os = "netbsd")] 78 | pub mod os { 79 | pub const FAMILY: &'static str = "unix"; 80 | pub const OS: &'static str = "netbsd"; 81 | pub const DLL_PREFIX: &'static str = "lib"; 82 | pub const DLL_SUFFIX: &'static str = ".so"; 83 | pub const DLL_EXTENSION: &'static str = "so"; 84 | pub const EXE_SUFFIX: &'static str = ""; 85 | pub const EXE_EXTENSION: &'static str = ""; 86 | } 87 | 88 | #[cfg(target_os = "openbsd")] 89 | pub mod os { 90 | pub const FAMILY: &'static str = "unix"; 91 | pub const OS: &'static str = "openbsd"; 92 | pub const DLL_PREFIX: &'static str = "lib"; 93 | pub const DLL_SUFFIX: &'static str = ".so"; 94 | pub const DLL_EXTENSION: &'static str = "so"; 95 | pub const EXE_SUFFIX: &'static str = ""; 96 | pub const EXE_EXTENSION: &'static str = ""; 97 | } 98 | 99 | #[cfg(target_os = "android")] 100 | pub mod os { 101 | pub const FAMILY: &'static str = "unix"; 102 | pub const OS: &'static str = "android"; 103 | pub const DLL_PREFIX: &'static str = "lib"; 104 | pub const DLL_SUFFIX: &'static str = ".so"; 105 | pub const DLL_EXTENSION: &'static str = "so"; 106 | pub const EXE_SUFFIX: &'static str = ""; 107 | pub const EXE_EXTENSION: &'static str = ""; 108 | } 109 | 110 | #[cfg(target_os = "solaris")] 111 | pub mod os { 112 | pub const FAMILY: &'static str = "unix"; 113 | pub const OS: &'static str = "solaris"; 114 | pub const DLL_PREFIX: &'static str = "lib"; 115 | pub const DLL_SUFFIX: &'static str = ".so"; 116 | pub const DLL_EXTENSION: &'static str = "so"; 117 | pub const EXE_SUFFIX: &'static str = ""; 118 | pub const EXE_EXTENSION: &'static str = ""; 119 | } 120 | 121 | #[cfg(all(target_os = "nacl", not(target_arch = "le32")))] 122 | pub mod os { 123 | pub const FAMILY: &'static str = "unix"; 124 | pub const OS: &'static str = "nacl"; 125 | pub const DLL_PREFIX: &'static str = "lib"; 126 | pub const DLL_SUFFIX: &'static str = ".so"; 127 | pub const DLL_EXTENSION: &'static str = "so"; 128 | pub const EXE_SUFFIX: &'static str = ".nexe"; 129 | pub const EXE_EXTENSION: &'static str = "nexe"; 130 | } 131 | #[cfg(all(target_os = "nacl", target_arch = "le32"))] 132 | pub mod os { 133 | pub const FAMILY: &'static str = "unix"; 134 | pub const OS: &'static str = "pnacl"; 135 | pub const DLL_PREFIX: &'static str = "lib"; 136 | pub const DLL_SUFFIX: &'static str = ".pso"; 137 | pub const DLL_EXTENSION: &'static str = "pso"; 138 | pub const EXE_SUFFIX: &'static str = ".pexe"; 139 | pub const EXE_EXTENSION: &'static str = "pexe"; 140 | } 141 | 142 | #[cfg(target_os = "haiku")] 143 | pub mod os { 144 | pub const FAMILY: &'static str = "unix"; 145 | pub const OS: &'static str = "haiku"; 146 | pub const DLL_PREFIX: &'static str = "lib"; 147 | pub const DLL_SUFFIX: &'static str = ".so"; 148 | pub const DLL_EXTENSION: &'static str = "so"; 149 | pub const EXE_SUFFIX: &'static str = ""; 150 | pub const EXE_EXTENSION: &'static str = ""; 151 | } 152 | 153 | #[cfg(all(target_os = "emscripten", target_arch = "asmjs"))] 154 | pub mod os { 155 | pub const FAMILY: &'static str = "unix"; 156 | pub const OS: &'static str = "emscripten"; 157 | pub const DLL_PREFIX: &'static str = "lib"; 158 | pub const DLL_SUFFIX: &'static str = ".so"; 159 | pub const DLL_EXTENSION: &'static str = "so"; 160 | pub const EXE_SUFFIX: &'static str = ".js"; 161 | pub const EXE_EXTENSION: &'static str = "js"; 162 | } 163 | 164 | #[cfg(all(target_os = "emscripten", target_arch = "wasm32"))] 165 | pub mod os { 166 | pub const FAMILY: &'static str = "unix"; 167 | pub const OS: &'static str = "emscripten"; 168 | pub const DLL_PREFIX: &'static str = "lib"; 169 | pub const DLL_SUFFIX: &'static str = ".so"; 170 | pub const DLL_EXTENSION: &'static str = "so"; 171 | pub const EXE_SUFFIX: &'static str = ".js"; 172 | pub const EXE_EXTENSION: &'static str = "js"; 173 | } 174 | 175 | #[cfg(target_os = "fuchsia")] 176 | pub mod os { 177 | pub const FAMILY: &'static str = "unix"; 178 | pub const OS: &'static str = "fuchsia"; 179 | pub const DLL_PREFIX: &'static str = "lib"; 180 | pub const DLL_SUFFIX: &'static str = ".so"; 181 | pub const DLL_EXTENSION: &'static str = "so"; 182 | pub const EXE_SUFFIX: &'static str = ""; 183 | pub const EXE_EXTENSION: &'static str = ""; 184 | } 185 | -------------------------------------------------------------------------------- /src/sys/linux/ext/ffi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Unix-specific extension to the primitives in the `std::ffi` module 12 | 13 | #![stable(feature = "rust1", since = "1.0.0")] 14 | 15 | use ffi::{OsStr, OsString}; 16 | use mem; 17 | use sys::os_str::Buf; 18 | use sys_common::{FromInner, IntoInner, AsInner}; 19 | 20 | /// Unix-specific extensions to `OsString`. 21 | #[stable(feature = "rust1", since = "1.0.0")] 22 | pub trait OsStringExt { 23 | /// Creates an [`OsString`] from a byte vector. 24 | /// 25 | /// # Examples 26 | /// 27 | /// ``` 28 | /// use std::ffi::OsString; 29 | /// use std::os::unix::ffi::OsStringExt; 30 | /// 31 | /// let bytes = b"foo".to_vec(); 32 | /// let os_string = OsString::from_vec(bytes); 33 | /// assert_eq!(os_string.to_str(), Some("foo")); 34 | /// ``` 35 | /// 36 | /// [`OsString`]: ../../../ffi/struct.OsString.html 37 | #[stable(feature = "rust1", since = "1.0.0")] 38 | fn from_vec(vec: Vec) -> Self; 39 | 40 | /// Yields the underlying byte vector of this [`OsString`]. 41 | /// 42 | /// # Examples 43 | /// 44 | /// ``` 45 | /// use std::ffi::OsString; 46 | /// use std::os::unix::ffi::OsStringExt; 47 | /// 48 | /// let mut os_string = OsString::new(); 49 | /// os_string.push("foo"); 50 | /// let bytes = os_string.into_vec(); 51 | /// assert_eq!(bytes, b"foo"); 52 | /// ``` 53 | /// 54 | /// [`OsString`]: ../../../ffi/struct.OsString.html 55 | #[stable(feature = "rust1", since = "1.0.0")] 56 | fn into_vec(self) -> Vec; 57 | } 58 | 59 | #[stable(feature = "rust1", since = "1.0.0")] 60 | impl OsStringExt for OsString { 61 | fn from_vec(vec: Vec) -> OsString { 62 | FromInner::from_inner(Buf { inner: vec }) 63 | } 64 | fn into_vec(self) -> Vec { 65 | self.into_inner().inner 66 | } 67 | } 68 | 69 | /// Unix-specific extensions to `OsStr`. 70 | #[stable(feature = "rust1", since = "1.0.0")] 71 | pub trait OsStrExt { 72 | #[stable(feature = "rust1", since = "1.0.0")] 73 | /// Creates an [`OsStr`] from a byte slice. 74 | /// 75 | /// # Examples 76 | /// 77 | /// ``` 78 | /// use std::ffi::OsStr; 79 | /// use std::os::unix::ffi::OsStrExt; 80 | /// 81 | /// let bytes = b"foo"; 82 | /// let os_str = OsStr::from_bytes(bytes); 83 | /// assert_eq!(os_str.to_str(), Some("foo")); 84 | /// ``` 85 | /// 86 | /// [`OsStr`]: ../../../ffi/struct.OsStr.html 87 | fn from_bytes(slice: &[u8]) -> &Self; 88 | 89 | /// Gets the underlying byte view of the [`OsStr`] slice. 90 | /// 91 | /// # Examples 92 | /// 93 | /// ``` 94 | /// use std::ffi::OsStr; 95 | /// use std::os::unix::ffi::OsStrExt; 96 | /// 97 | /// let mut os_str = OsStr::new("foo"); 98 | /// let bytes = os_str.as_bytes(); 99 | /// assert_eq!(bytes, b"foo"); 100 | /// ``` 101 | /// 102 | /// [`OsStr`]: ../../../ffi/struct.OsStr.html 103 | #[stable(feature = "rust1", since = "1.0.0")] 104 | fn as_bytes(&self) -> &[u8]; 105 | } 106 | 107 | #[stable(feature = "rust1", since = "1.0.0")] 108 | impl OsStrExt for OsStr { 109 | fn from_bytes(slice: &[u8]) -> &OsStr { 110 | unsafe { mem::transmute(slice) } 111 | } 112 | fn as_bytes(&self) -> &[u8] { 113 | &self.as_inner().inner 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/sys/linux/ext/io.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Unix-specific extensions to general I/O primitives 12 | 13 | #![stable(feature = "rust1", since = "1.0.0")] 14 | 15 | use fs; 16 | use net; 17 | use os::raw; 18 | use sys; 19 | use sys_common::{self, AsInner, FromInner, IntoInner}; 20 | 21 | /// Raw file descriptors. 22 | #[stable(feature = "rust1", since = "1.0.0")] 23 | pub type RawFd = raw::c_int; 24 | 25 | /// A trait to extract the raw unix file descriptor from an underlying 26 | /// object. 27 | /// 28 | /// This is only available on unix platforms and must be imported in order 29 | /// to call the method. Windows platforms have a corresponding `AsRawHandle` 30 | /// and `AsRawSocket` set of traits. 31 | #[stable(feature = "rust1", since = "1.0.0")] 32 | pub trait AsRawFd { 33 | /// Extracts the raw file descriptor. 34 | /// 35 | /// This method does **not** pass ownership of the raw file descriptor 36 | /// to the caller. The descriptor is only guaranteed to be valid while 37 | /// the original object has not yet been destroyed. 38 | #[stable(feature = "rust1", since = "1.0.0")] 39 | fn as_raw_fd(&self) -> RawFd; 40 | } 41 | 42 | /// A trait to express the ability to construct an object from a raw file 43 | /// descriptor. 44 | #[stable(feature = "from_raw_os", since = "1.1.0")] 45 | pub trait FromRawFd { 46 | /// Constructs a new instance of `Self` from the given raw file 47 | /// descriptor. 48 | /// 49 | /// This function **consumes ownership** of the specified file 50 | /// descriptor. The returned object will take responsibility for closing 51 | /// it when the object goes out of scope. 52 | /// 53 | /// This function is also unsafe as the primitives currently returned 54 | /// have the contract that they are the sole owner of the file 55 | /// descriptor they are wrapping. Usage of this function could 56 | /// accidentally allow violating this contract which can cause memory 57 | /// unsafety in code that relies on it being true. 58 | #[stable(feature = "from_raw_os", since = "1.1.0")] 59 | unsafe fn from_raw_fd(fd: RawFd) -> Self; 60 | } 61 | 62 | /// A trait to express the ability to consume an object and acquire ownership of 63 | /// its raw file descriptor. 64 | #[stable(feature = "into_raw_os", since = "1.4.0")] 65 | pub trait IntoRawFd { 66 | /// Consumes this object, returning the raw underlying file descriptor. 67 | /// 68 | /// This function **transfers ownership** of the underlying file descriptor 69 | /// to the caller. Callers are then the unique owners of the file descriptor 70 | /// and must close the descriptor once it's no longer needed. 71 | #[stable(feature = "into_raw_os", since = "1.4.0")] 72 | fn into_raw_fd(self) -> RawFd; 73 | } 74 | 75 | #[stable(feature = "rust1", since = "1.0.0")] 76 | impl AsRawFd for fs::File { 77 | fn as_raw_fd(&self) -> RawFd { 78 | self.as_inner().fd().raw() 79 | } 80 | } 81 | #[stable(feature = "from_raw_os", since = "1.1.0")] 82 | impl FromRawFd for fs::File { 83 | unsafe fn from_raw_fd(fd: RawFd) -> fs::File { 84 | fs::File::from_inner(sys::fs::File::from_inner(fd)) 85 | } 86 | } 87 | #[stable(feature = "into_raw_os", since = "1.4.0")] 88 | impl IntoRawFd for fs::File { 89 | fn into_raw_fd(self) -> RawFd { 90 | self.into_inner().into_fd().into_raw() 91 | } 92 | } 93 | 94 | #[stable(feature = "rust1", since = "1.0.0")] 95 | impl AsRawFd for net::TcpStream { 96 | fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } 97 | } 98 | #[stable(feature = "rust1", since = "1.0.0")] 99 | impl AsRawFd for net::TcpListener { 100 | fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } 101 | } 102 | #[stable(feature = "rust1", since = "1.0.0")] 103 | impl AsRawFd for net::UdpSocket { 104 | fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } 105 | } 106 | 107 | #[stable(feature = "from_raw_os", since = "1.1.0")] 108 | impl FromRawFd for net::TcpStream { 109 | unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { 110 | let socket = sys::net::Socket::from_inner(fd); 111 | net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) 112 | } 113 | } 114 | #[stable(feature = "from_raw_os", since = "1.1.0")] 115 | impl FromRawFd for net::TcpListener { 116 | unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { 117 | let socket = sys::net::Socket::from_inner(fd); 118 | net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) 119 | } 120 | } 121 | #[stable(feature = "from_raw_os", since = "1.1.0")] 122 | impl FromRawFd for net::UdpSocket { 123 | unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { 124 | let socket = sys::net::Socket::from_inner(fd); 125 | net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) 126 | } 127 | } 128 | 129 | #[stable(feature = "into_raw_os", since = "1.4.0")] 130 | impl IntoRawFd for net::TcpStream { 131 | fn into_raw_fd(self) -> RawFd { 132 | self.into_inner().into_socket().into_inner() 133 | } 134 | } 135 | #[stable(feature = "into_raw_os", since = "1.4.0")] 136 | impl IntoRawFd for net::TcpListener { 137 | fn into_raw_fd(self) -> RawFd { 138 | self.into_inner().into_socket().into_inner() 139 | } 140 | } 141 | #[stable(feature = "into_raw_os", since = "1.4.0")] 142 | impl IntoRawFd for net::UdpSocket { 143 | fn into_raw_fd(self) -> RawFd { 144 | self.into_inner().into_socket().into_inner() 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/sys/linux/ext/mod.rs: -------------------------------------------------------------------------------- 1 | #![unstable(feature = "steed", issue = "0")] 2 | // NOTE(japaric) ^ unsure why this is needed ... 3 | 4 | // Rust 1.16.0 5 | pub mod ffi; 6 | // Rust 1.16.0 7 | pub mod fs; 8 | // Rust 1.16.0 9 | pub mod io; 10 | // Rust 1.16.0 (no tests) 11 | pub mod net; 12 | 13 | #[stable(feature = "steed", since = "1.0.0")] 14 | pub mod prelude { 15 | #[doc(no_inline)] #[stable(feature = "steed", since = "1.0.0")] 16 | pub use super::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; 17 | #[doc(no_inline)] #[stable(feature = "steed", since = "1.0.0")] 18 | pub use super::ffi::{OsStrExt, OsStringExt}; 19 | #[doc(no_inline)] #[stable(feature = "steed", since = "1.0.0")] 20 | pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt}; 21 | #[doc(no_inline)] #[stable(feature = "steed", since = "1.0.0")] 22 | pub use super::fs::DirEntryExt; 23 | #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")] 24 | pub use super::fs::FileExt; 25 | /* 26 | #[doc(no_inline)] #[stable(feature = "steed", since = "1.0.0")] 27 | pub use super::thread::JoinHandleExt; 28 | #[doc(no_inline)] #[stable(feature = "steed", since = "1.0.0")] 29 | pub use super::process::{CommandExt, ExitStatusExt}; 30 | */ 31 | } 32 | -------------------------------------------------------------------------------- /src/sys/linux/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | // Rust 1.16.0 4 | pub mod args; 5 | // Rust 1.16.0 6 | pub mod env; 7 | pub mod ext; 8 | // Rust 1.16.0 (very close) 9 | pub mod fd; 10 | // Rust 1.16.0 (own implementation of readdir and canonicalize) 11 | pub mod fs; 12 | pub mod memchr; 13 | pub mod mutex; 14 | // Rust 1.16.0 (without error support for `lookup_host`, minor changes) 15 | pub mod net; 16 | // Rust 1.16.0 17 | pub mod os_str; 18 | // parking_lot 0.4.1, parking_lot_core 0.2.1 19 | // https://github.com/Amanieu/parking_lot 20 | // 73542a955a00e1d785d263d01c61c37da5032474 21 | // (adapted) 22 | pub mod parking_lot; 23 | // Rust 1.16.0 24 | pub mod path; 25 | pub mod pipe; 26 | #[cfg_attr(not(issue = "11"), allow(unused_imports))] 27 | #[cfg_attr(not(issue = "11"), allow(unused_variables))] 28 | pub mod process; 29 | pub mod os; 30 | pub mod rand; 31 | pub mod stack_overflow; 32 | pub mod time; 33 | // Rust 1.15.0 34 | pub mod thread; 35 | 36 | pub use os::linux as platform; 37 | 38 | use intrinsics; 39 | use io::Error; 40 | use io::ErrorKind; 41 | use io::Result; 42 | use libc; 43 | 44 | // Rust 1.16.0: src/libstd/sys/unix/mod.rs 45 | pub fn decode_error_kind(errno: i32) -> ErrorKind { 46 | match errno as libc::c_int { 47 | libc::ECONNREFUSED => ErrorKind::ConnectionRefused, 48 | libc::ECONNRESET => ErrorKind::ConnectionReset, 49 | libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, 50 | libc::EPIPE => ErrorKind::BrokenPipe, 51 | libc::ENOTCONN => ErrorKind::NotConnected, 52 | libc::ECONNABORTED => ErrorKind::ConnectionAborted, 53 | libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, 54 | libc::EADDRINUSE => ErrorKind::AddrInUse, 55 | libc::ENOENT => ErrorKind::NotFound, 56 | libc::EINTR => ErrorKind::Interrupted, 57 | libc::EINVAL => ErrorKind::InvalidInput, 58 | libc::ETIMEDOUT => ErrorKind::TimedOut, 59 | libc::EEXIST => ErrorKind::AlreadyExists, 60 | 61 | // These two constants can have the same value on some systems, 62 | // but different values on others, so we can't use a match 63 | // clause 64 | x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => 65 | ErrorKind::WouldBlock, 66 | 67 | _ => ErrorKind::Other, 68 | } 69 | } 70 | 71 | pub trait Cvt: Copy { 72 | fn cvt(self) -> Result; 73 | } 74 | 75 | macro_rules! impl_cvt { 76 | ($($t:ident)*) => ($(impl Cvt for $t { 77 | fn cvt(self) -> Result<$t> { 78 | if self < 0 { 79 | assert!(self >= -0x7fff_ffff); 80 | Err(Error::from_raw_os_error(-(self as i32))) 81 | } else { 82 | Ok(self) 83 | } 84 | } 85 | })*) 86 | } 87 | 88 | impl_cvt! { i32 isize i64 } 89 | 90 | pub fn cvt(ret: I) -> Result { 91 | ret.cvt() 92 | } 93 | 94 | pub fn cvtu(ret: isize) -> Result { 95 | cvt(ret).map(|r| r as usize) 96 | } 97 | 98 | pub fn cvt_r I>(mut f: F) -> Result { 99 | loop { 100 | match cvt(f()) { 101 | Err(ref e) if e.kind() == ErrorKind::Interrupted => {} 102 | other => return other, 103 | } 104 | } 105 | } 106 | 107 | pub unsafe fn abort_internal() -> ! { 108 | intrinsics::abort() 109 | } 110 | -------------------------------------------------------------------------------- /src/sys/linux/mutex.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use super::parking_lot; 12 | 13 | pub struct Mutex { inner: parking_lot::RawMutex } 14 | 15 | unsafe impl Send for Mutex {} 16 | unsafe impl Sync for Mutex {} 17 | 18 | #[allow(dead_code)] // sys isn't exported yet 19 | impl Mutex { 20 | pub const fn new() -> Mutex { 21 | // Might be moved and address is changing it is better to avoid 22 | // initialization of potentially opaque OS data before it landed 23 | Mutex { inner: parking_lot::RawMutex::new() } 24 | } 25 | #[inline] 26 | pub unsafe fn init(&mut self) { 27 | } 28 | #[inline] 29 | pub unsafe fn lock(&self) { 30 | self.inner.lock() 31 | } 32 | #[inline] 33 | pub unsafe fn unlock(&self) { 34 | self.inner.unlock(false) 35 | } 36 | #[inline] 37 | pub unsafe fn try_lock(&self) -> bool { 38 | self.inner.try_lock() 39 | } 40 | #[inline] 41 | pub unsafe fn destroy(&self) { 42 | } 43 | } 44 | 45 | /* 46 | pub struct ReentrantMutex { inner: UnsafeCell } 47 | 48 | unsafe impl Send for ReentrantMutex {} 49 | unsafe impl Sync for ReentrantMutex {} 50 | 51 | impl ReentrantMutex { 52 | pub unsafe fn uninitialized() -> ReentrantMutex { 53 | ReentrantMutex { inner: mem::uninitialized() } 54 | } 55 | 56 | pub unsafe fn init(&mut self) { 57 | let mut attr: libc::pthread_mutexattr_t = mem::uninitialized(); 58 | let result = libc::pthread_mutexattr_init(&mut attr as *mut _); 59 | debug_assert_eq!(result, 0); 60 | let result = libc::pthread_mutexattr_settype(&mut attr as *mut _, 61 | libc::PTHREAD_MUTEX_RECURSIVE); 62 | debug_assert_eq!(result, 0); 63 | let result = libc::pthread_mutex_init(self.inner.get(), &attr as *const _); 64 | debug_assert_eq!(result, 0); 65 | let result = libc::pthread_mutexattr_destroy(&mut attr as *mut _); 66 | debug_assert_eq!(result, 0); 67 | } 68 | 69 | pub unsafe fn lock(&self) { 70 | let result = libc::pthread_mutex_lock(self.inner.get()); 71 | debug_assert_eq!(result, 0); 72 | } 73 | 74 | #[inline] 75 | pub unsafe fn try_lock(&self) -> bool { 76 | libc::pthread_mutex_trylock(self.inner.get()) == 0 77 | } 78 | 79 | pub unsafe fn unlock(&self) { 80 | let result = libc::pthread_mutex_unlock(self.inner.get()); 81 | debug_assert_eq!(result, 0); 82 | } 83 | 84 | pub unsafe fn destroy(&self) { 85 | let result = libc::pthread_mutex_destroy(self.inner.get()); 86 | debug_assert_eq!(result, 0); 87 | } 88 | } 89 | */ 90 | -------------------------------------------------------------------------------- /src/sys/linux/os.rs: -------------------------------------------------------------------------------- 1 | use ctypes::c_char; 2 | use error::Error as StdError; 3 | use ffi::{CStr, CString, OsStr, OsString}; 4 | use fmt; 5 | use io; 6 | use iter; 7 | use libc; 8 | use linux; 9 | use marker::PhantomData; 10 | use path::{self, PathBuf}; 11 | use slice; 12 | use super::cvt; 13 | use sys::ext::prelude::*; 14 | use vec; 15 | 16 | static ENV_LOCK: () = (); 17 | // TODO(steed, #143): Synchronize environment access once we have mutexes. 18 | trait MutexExt { 19 | fn lock(&self) { } 20 | fn unlock(&self) { } 21 | } 22 | impl MutexExt for () { } 23 | 24 | pub fn errno() -> i32 { 25 | panic!("no C-compatible errno variable"); 26 | } 27 | 28 | pub fn error_string(errno: i32) -> String { 29 | linux::errno::error_string(errno).map(|s| s.into()).unwrap_or_else(|| { 30 | format!("Unknown OS error ({})", errno) 31 | }) 32 | } 33 | 34 | pub fn exit(code: i32) -> ! { 35 | unsafe { libc::exit_group(code) } 36 | } 37 | 38 | pub fn getcwd() -> io::Result { 39 | let mut buf = Vec::with_capacity(512); 40 | loop { 41 | unsafe { 42 | let ptr = buf.as_mut_ptr() as *mut libc::c_char; 43 | match cvt(libc::getcwd(ptr, buf.capacity())) { 44 | Ok(_) => { 45 | let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len(); 46 | buf.set_len(len); 47 | buf.shrink_to_fit(); 48 | return Ok(PathBuf::from(OsString::from_vec(buf))); 49 | }, 50 | Err(ref e) if e.raw_os_error() == Some(libc::ERANGE) => {}, 51 | Err(e) => return Err(e), 52 | } 53 | 54 | // Trigger the internal buffer resizing logic of `Vec` by requiring 55 | // more space than the current capacity. 56 | let cap = buf.capacity(); 57 | buf.set_len(cap); 58 | buf.reserve(1); 59 | } 60 | } 61 | } 62 | 63 | pub fn page_size() -> usize { 64 | // TODO(steed, #133): Implement me. 65 | unimplemented!(); 66 | } 67 | 68 | pub fn chdir(p: &path::Path) -> io::Result<()> { 69 | let p: &OsStr = p.as_ref(); 70 | let p = CString::new(p.as_bytes())?; 71 | unsafe { 72 | cvt(libc::chdir(p.as_ptr())).map(|_| ()) 73 | } 74 | } 75 | 76 | pub struct SplitPaths<'a> { 77 | iter: iter::Map bool>, 78 | fn(&'a [u8]) -> PathBuf>, 79 | } 80 | 81 | pub fn split_paths(unparsed: &OsStr) -> SplitPaths { 82 | fn bytes_to_path(b: &[u8]) -> PathBuf { 83 | PathBuf::from(::from_bytes(b)) 84 | } 85 | fn is_colon(b: &u8) -> bool { *b == b':' } 86 | let unparsed = unparsed.as_bytes(); 87 | SplitPaths { 88 | iter: unparsed.split(is_colon as fn(&u8) -> bool) 89 | .map(bytes_to_path as fn(&[u8]) -> PathBuf) 90 | } 91 | } 92 | 93 | impl<'a> Iterator for SplitPaths<'a> { 94 | type Item = PathBuf; 95 | fn next(&mut self) -> Option { self.iter.next() } 96 | fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } 97 | } 98 | 99 | #[derive(Debug)] 100 | pub struct JoinPathsError; 101 | 102 | pub fn join_paths(paths: I) -> Result 103 | where I: Iterator, T: AsRef 104 | { 105 | let mut joined = Vec::new(); 106 | let sep = b':'; 107 | 108 | for (i, path) in paths.enumerate() { 109 | let path = path.as_ref().as_bytes(); 110 | if i > 0 { joined.push(sep) } 111 | if path.contains(&sep) { 112 | return Err(JoinPathsError) 113 | } 114 | joined.extend_from_slice(path); 115 | } 116 | Ok(OsStringExt::from_vec(joined)) 117 | } 118 | 119 | impl fmt::Display for JoinPathsError { 120 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 121 | "path segment contains separator `:`".fmt(f) 122 | } 123 | } 124 | 125 | impl StdError for JoinPathsError { 126 | fn description(&self) -> &str { "failed to join paths" } 127 | } 128 | 129 | pub fn current_exe() -> io::Result { 130 | ::fs::read_link("/proc/self/exe") 131 | } 132 | 133 | pub unsafe fn environ() -> *const *const c_char { 134 | libc::environ() 135 | } 136 | 137 | pub struct Env { 138 | iter: vec::IntoIter<(OsString, OsString)>, 139 | _dont_send_or_sync_me: PhantomData<*mut ()>, 140 | } 141 | 142 | impl Iterator for Env { 143 | type Item = (OsString, OsString); 144 | fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() } 145 | fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } 146 | } 147 | 148 | /// Returns a vector of (variable, value) byte-vector pairs for all the 149 | /// environment variables of the current process. 150 | pub fn env() -> Env { 151 | fn os_string(slice: &[u8]) -> OsString { 152 | OsString::from_vec(slice.to_owned()) 153 | } 154 | unsafe { 155 | ENV_LOCK.lock(); 156 | let result = Env { 157 | iter: libc::env().values() 158 | .map(|kv| (os_string(&kv.key), os_string(&kv.value))) 159 | .collect::>() 160 | .into_iter(), 161 | _dont_send_or_sync_me: PhantomData, 162 | }; 163 | ENV_LOCK.unlock(); 164 | result 165 | } 166 | } 167 | 168 | pub fn getenv(k: &OsStr) -> io::Result> { 169 | // environment variables with a nul byte can't be set, so their value is 170 | // always None as well 171 | let k = CString::new(k.as_bytes())?; 172 | unsafe { 173 | ENV_LOCK.lock(); 174 | let s = libc::getenv(k.as_bytes()).map(|v| OsString::from_vec(v.to_owned())); 175 | ENV_LOCK.unlock(); 176 | return Ok(s) 177 | } 178 | } 179 | 180 | pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { 181 | unsafe { 182 | ENV_LOCK.lock(); 183 | let result = cvt(libc::setenv(k.as_bytes(), v.as_bytes())).map(|_| ()); 184 | ENV_LOCK.unlock(); 185 | result 186 | } 187 | } 188 | 189 | pub fn unsetenv(k: &OsStr) -> io::Result<()> { 190 | unsafe { 191 | ENV_LOCK.lock(); 192 | let ret = cvt(libc::unsetenv(k.as_bytes())).map(|_| ()); 193 | ENV_LOCK.unlock(); 194 | return ret 195 | } 196 | } 197 | 198 | pub fn temp_dir() -> PathBuf { 199 | ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { 200 | if cfg!(target_os = "android") { 201 | PathBuf::from("/data/local/tmp") 202 | } else { 203 | PathBuf::from("/tmp") 204 | } 205 | }) 206 | } 207 | -------------------------------------------------------------------------------- /src/sys/linux/os_str.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | /// The underlying OsString/OsStr implementation on Unix systems: just 12 | /// a `Vec`/`[u8]`. 13 | 14 | use borrow::Cow; 15 | use fmt::{self, Debug}; 16 | use str; 17 | use mem; 18 | use sys_common::{AsInner, IntoInner}; 19 | 20 | #[derive(Clone, Hash)] 21 | pub struct Buf { 22 | pub inner: Vec 23 | } 24 | 25 | pub struct Slice { 26 | pub inner: [u8] 27 | } 28 | 29 | impl Debug for Slice { 30 | fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { 31 | self.to_string_lossy().fmt(formatter) 32 | } 33 | } 34 | 35 | impl Debug for Buf { 36 | fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { 37 | self.as_slice().fmt(formatter) 38 | } 39 | } 40 | 41 | impl IntoInner> for Buf { 42 | fn into_inner(self) -> Vec { 43 | self.inner 44 | } 45 | } 46 | 47 | impl AsInner<[u8]> for Buf { 48 | fn as_inner(&self) -> &[u8] { 49 | &self.inner 50 | } 51 | } 52 | 53 | 54 | impl Buf { 55 | pub fn from_string(s: String) -> Buf { 56 | Buf { inner: s.into_bytes() } 57 | } 58 | 59 | #[inline] 60 | pub fn with_capacity(capacity: usize) -> Buf { 61 | Buf { 62 | inner: Vec::with_capacity(capacity) 63 | } 64 | } 65 | 66 | #[inline] 67 | pub fn clear(&mut self) { 68 | self.inner.clear() 69 | } 70 | 71 | #[inline] 72 | pub fn capacity(&self) -> usize { 73 | self.inner.capacity() 74 | } 75 | 76 | #[inline] 77 | pub fn reserve(&mut self, additional: usize) { 78 | self.inner.reserve(additional) 79 | } 80 | 81 | #[inline] 82 | pub fn reserve_exact(&mut self, additional: usize) { 83 | self.inner.reserve_exact(additional) 84 | } 85 | 86 | pub fn as_slice(&self) -> &Slice { 87 | unsafe { mem::transmute(&*self.inner) } 88 | } 89 | 90 | pub fn into_string(self) -> Result { 91 | String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } ) 92 | } 93 | 94 | pub fn push_slice(&mut self, s: &Slice) { 95 | self.inner.extend_from_slice(&s.inner) 96 | } 97 | } 98 | 99 | impl Slice { 100 | fn from_u8_slice(s: &[u8]) -> &Slice { 101 | unsafe { mem::transmute(s) } 102 | } 103 | 104 | pub fn from_str(s: &str) -> &Slice { 105 | Slice::from_u8_slice(s.as_bytes()) 106 | } 107 | 108 | pub fn to_str(&self) -> Option<&str> { 109 | str::from_utf8(&self.inner).ok() 110 | } 111 | 112 | pub fn to_string_lossy(&self) -> Cow { 113 | String::from_utf8_lossy(&self.inner) 114 | } 115 | 116 | pub fn to_owned(&self) -> Buf { 117 | Buf { inner: self.inner.to_vec() } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/sys/linux/parking_lot/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /src/sys/linux/parking_lot/core/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! This library exposes a low-level API for creating your own efficient 9 | //! synchronization primitives. 10 | //! 11 | //! # The parking lot 12 | //! 13 | //! To keep synchronization primitives small, all thread queuing and suspending 14 | //! functionality is offloaded to the *parking lot*. The idea behind this is 15 | //! based on the Webkit [`WTF::ParkingLot`] 16 | //! (https://webkit.org/blog/6161/locking-in-webkit/) class, which essentially 17 | //! consists of a hash table mapping of lock addresses to queues of parked 18 | //! (sleeping) threads. The Webkit parking lot was itself inspired by Linux 19 | //! [futexes](http://man7.org/linux/man-pages/man2/futex.2.html), but it is more 20 | //! powerful since it allows invoking callbacks while holding a queue lock. 21 | //! 22 | //! There are two main operations that can be performed on the parking lot: 23 | //! - *Parking* refers to suspending the thread while simultaneously enqueuing it 24 | //! on a queue keyed by some address. 25 | //! - *Unparking* refers to dequeuing a thread from a queue keyed by some address 26 | //! and resuming it. 27 | //! 28 | //! See the documentation of the individual functions for more details. 29 | //! 30 | //! # Building custom synchronization primitives 31 | //! 32 | //! Building custom synchronization primitives is very simple since the parking 33 | //! lot takes care of all the hard parts for you. A simple example for a 34 | //! custom primitive would be to integrate a `Mutex` inside another data type. 35 | //! Since a mutex only requires 2 bits, it can share space with other data. 36 | //! For example, one could create an `ArcMutex` type that combines the atomic 37 | //! reference count and the two mutex bits in the same atomic word. 38 | 39 | #![warn(missing_docs)] 40 | 41 | /* 42 | extern crate rand; 43 | extern crate smallvec; 44 | */ 45 | 46 | #[path = "thread_parker/linux.rs"] 47 | mod thread_parker; 48 | 49 | mod util; 50 | mod spinwait; 51 | pub mod word_lock; 52 | pub mod parking_lot; 53 | 54 | pub use self::parking_lot::{ParkResult, UnparkResult, RequeueOp, UnparkToken, ParkToken, FilterOp}; 55 | pub use self::parking_lot::{DEFAULT_UNPARK_TOKEN, DEFAULT_PARK_TOKEN}; 56 | pub use self::parking_lot::{park, unpark_one, unpark_all, unpark_requeue, unpark_filter}; 57 | pub use self::spinwait::SpinWait; 58 | -------------------------------------------------------------------------------- /src/sys/linux/parking_lot/core/spinwait.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use libc; 9 | 10 | #[inline] 11 | fn thread_yield() { 12 | unsafe { 13 | libc::sched_yield(); 14 | } 15 | } 16 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 17 | #[inline] 18 | fn cpu_relax(iterations: u32) { 19 | for _ in 0..iterations { 20 | unsafe { 21 | asm!("pause" ::: "memory" : "volatile"); 22 | } 23 | } 24 | } 25 | #[cfg(target_arch = "aarch64")] 26 | #[inline] 27 | fn cpu_relax(iterations: u32) { 28 | for _ in 0..iterations { 29 | unsafe { 30 | asm!("yield" ::: "memory" : "volatile"); 31 | } 32 | } 33 | } 34 | #[cfg(not(any(target_arch = "x86", 35 | target_arch = "x86_64", 36 | target_arch = "aarch64")))] 37 | #[inline] 38 | fn cpu_relax(iterations: u32) { 39 | for _ in 0..iterations { 40 | unsafe { 41 | asm!("" ::: "memory" : "volatile"); 42 | } 43 | } 44 | } 45 | 46 | /// A counter used to perform exponential backoff in spin loops. 47 | pub struct SpinWait { 48 | counter: u32, 49 | } 50 | 51 | impl SpinWait { 52 | /// Creates a new `SpinWait`. 53 | #[inline] 54 | pub const fn new() -> SpinWait { 55 | SpinWait { counter: 0 } 56 | } 57 | 58 | /// Resets a `SpinWait` to its initial state. 59 | #[inline] 60 | pub fn reset(&mut self) { 61 | self.counter = 0; 62 | } 63 | 64 | /// Spins until the sleep threshold has been reached. 65 | /// 66 | /// This function returns whether the sleep threshold has been reached, at 67 | /// which point further spinning has diminishing returns and the thread 68 | /// should be parked instead. 69 | /// 70 | /// The spin strategy will initially use a CPU-bound loop but will fall back 71 | /// to yielding the CPU to the OS after a few iterations. 72 | #[inline] 73 | pub fn spin(&mut self) -> bool { 74 | if self.counter >= 20 { 75 | return false; 76 | } 77 | self.counter += 1; 78 | if self.counter <= 10 { 79 | cpu_relax(4 << self.counter); 80 | } else { 81 | thread_yield(); 82 | } 83 | true 84 | } 85 | 86 | /// Spins without yielding the thread to the OS. 87 | /// 88 | /// Instead, the backoff is simply capped at a maximum value. This can be 89 | /// used to improve throughput in `compare_exchange` loops that have high 90 | /// contention. 91 | #[inline] 92 | pub fn spin_no_yield(&mut self) { 93 | self.counter += 1; 94 | if self.counter > 10 { 95 | self.counter = 10; 96 | } 97 | cpu_relax(4 << self.counter); 98 | } 99 | } 100 | 101 | impl Default for SpinWait { 102 | #[inline] 103 | fn default() -> SpinWait { 104 | SpinWait::new() 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/sys/linux/parking_lot/core/thread_parker/linux.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use libc; 9 | use linux::{self, FUTEX_PRIVATE, FUTEX_WAIT, FUTEX_WAKE}; 10 | use ptr; 11 | use sync::atomic::{AtomicI32, Ordering}; 12 | use time::Instant; 13 | 14 | #[inline(always)] 15 | pub unsafe fn futex(uaddr: *const AtomicI32, 16 | op: libc::c_int, 17 | val: i32, 18 | utime: *const libc::timespec) 19 | -> libc::c_int 20 | { 21 | linux::futex(uaddr as *mut _, op, val as u32, utime, ptr::null_mut(), 0) 22 | } 23 | 24 | // Helper type for putting a thread to sleep until some other thread wakes it up 25 | pub struct ThreadParker { 26 | futex: AtomicI32, 27 | } 28 | 29 | impl ThreadParker { 30 | pub fn new() -> ThreadParker { 31 | ThreadParker { futex: AtomicI32::new(0) } 32 | } 33 | 34 | // Prepares the parker. This should be called before adding it to the queue. 35 | pub unsafe fn prepare_park(&self) { 36 | self.futex.store(1, Ordering::Relaxed); 37 | } 38 | 39 | // Checks if the park timed out. This should be called while holding the 40 | // queue lock after park_until has returned false. 41 | pub unsafe fn timed_out(&self) -> bool { 42 | self.futex.load(Ordering::Relaxed) != 0 43 | } 44 | 45 | // Parks the thread until it is unparked. This should be called after it has 46 | // been added to the queue, after unlocking the queue. 47 | pub unsafe fn park(&self) { 48 | while self.futex.load(Ordering::Acquire) != 0 { 49 | let r = futex(&self.futex, FUTEX_WAIT | FUTEX_PRIVATE, 1, ptr::null()); 50 | debug_assert!(r == 0 || 51 | r == -libc::EINTR || 52 | r == -libc::EAGAIN); 53 | } 54 | } 55 | 56 | // Parks the thread until it is unparked or the timeout is reached. This 57 | // should be called after it has been added to the queue, after unlocking 58 | // the queue. Returns true if we were unparked and false if we timed out. 59 | pub unsafe fn park_until(&self, timeout: Instant) -> bool { 60 | while self.futex.load(Ordering::Acquire) != 0 { 61 | let now = Instant::now(); 62 | if timeout <= now { 63 | return false; 64 | } 65 | let diff = timeout - now; 66 | if diff.as_secs() as libc::time_t as u64 != diff.as_secs() { 67 | // Timeout overflowed, just sleep indefinitely 68 | self.park(); 69 | return true; 70 | } 71 | let ts = libc::timespec { 72 | tv_sec: diff.as_secs() as libc::time_t, 73 | tv_nsec: diff.subsec_nanos() as libc::c_long, 74 | }; 75 | let r = futex(&self.futex, FUTEX_WAIT | FUTEX_PRIVATE, 1, &ts); 76 | debug_assert!(r == 0 || 77 | r == -libc::EINTR || 78 | r == -libc::EAGAIN || 79 | r == -libc::ETIMEDOUT); 80 | } 81 | true 82 | } 83 | 84 | // Locks the parker to prevent the target thread from exiting. This is 85 | // necessary to ensure that thread-local ThreadData objects remain valid. 86 | // This should be called while holding the queue lock. 87 | pub unsafe fn unpark_lock(&self) -> UnparkHandle { 88 | // We don't need to lock anything, just clear the state 89 | self.futex.store(0, Ordering::Release); 90 | 91 | UnparkHandle { futex: &self.futex } 92 | } 93 | } 94 | 95 | // Handle for a thread that is about to be unparked. We need to mark the thread 96 | // as unparked while holding the queue lock, but we delay the actual unparking 97 | // until after the queue lock is released. 98 | pub struct UnparkHandle { 99 | futex: *const AtomicI32, 100 | } 101 | 102 | impl UnparkHandle { 103 | // Wakes up the parked thread. This should be called after the queue lock is 104 | // released to avoid blocking the queue for too long. 105 | pub unsafe fn unpark(self) { 106 | // The thread data may have been freed at this point, but it doesn't 107 | // matter since the syscall will just return EFAULT in that case. 108 | let r = futex(self.futex, FUTEX_WAKE | FUTEX_PRIVATE, 1, ptr::null()); 109 | debug_assert!(r == 0 || 110 | r == 1 || 111 | r == -libc::EFAULT); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/sys/linux/parking_lot/core/util.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | // Option::unchecked_unwrap 9 | pub trait UncheckedOptionExt { 10 | unsafe fn unchecked_unwrap(self) -> T; 11 | } 12 | 13 | impl UncheckedOptionExt for Option { 14 | #[inline] 15 | unsafe fn unchecked_unwrap(self) -> T { 16 | match self { 17 | Some(x) => x, 18 | None => unreachable(), 19 | } 20 | } 21 | } 22 | 23 | // Equivalent to intrinsics::unreachable() in release mode 24 | #[inline] 25 | unsafe fn unreachable() -> ! { 26 | if cfg!(debug_assertions) { 27 | unreachable!(); 28 | } else { 29 | enum Void {} 30 | match *(1 as *const Void) {} 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/sys/linux/parking_lot/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | pub mod core; 4 | pub mod raw_mutex; 5 | 6 | pub use self::core as parking_lot_core; 7 | pub use self::raw_mutex::RawMutex; 8 | -------------------------------------------------------------------------------- /src/sys/linux/path.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use path::Prefix; 12 | use ffi::OsStr; 13 | 14 | #[inline] 15 | pub fn is_sep_byte(b: u8) -> bool { 16 | b == b'/' 17 | } 18 | 19 | #[inline] 20 | pub fn is_verbatim_sep(b: u8) -> bool { 21 | b == b'/' 22 | } 23 | 24 | pub fn parse_prefix(_: &OsStr) -> Option { 25 | None 26 | } 27 | 28 | pub const MAIN_SEP_STR: &'static str = "/"; 29 | pub const MAIN_SEP: char = '/'; 30 | -------------------------------------------------------------------------------- /src/sys/linux/pipe.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(unused)] 3 | 4 | pub enum read2 { } 5 | use sync::atomic::{AtomicBool, Ordering}; 6 | use cmp; 7 | use io; 8 | use linux::errno; 9 | use linux; 10 | use mem; 11 | use ptr; 12 | use sys::cvt; 13 | use sys::fd::FileDesc; 14 | 15 | //////////////////////////////////////////////////////////////////////////////// 16 | // Anonymous pipes 17 | //////////////////////////////////////////////////////////////////////////////// 18 | 19 | pub struct AnonPipe(FileDesc); 20 | 21 | pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { 22 | let mut fds = [0; 2]; 23 | 24 | // Unfortunately the only known way right now to create atomically set the 25 | // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in 26 | // 2.6.27, however, and because we support 2.6.18 we must detect this 27 | // support dynamically. 28 | static TRY_PIPE2: AtomicBool = AtomicBool::new(true); 29 | if TRY_PIPE2.load(Ordering::Relaxed) { 30 | match cvt(unsafe { linux::pipe2(fds.as_mut_ptr(), linux::O_CLOEXEC) }) { 31 | Err(ref e) if e.raw_os_error() == Some(errno::ENOSYS) => { 32 | TRY_PIPE2.store(false, Ordering::Relaxed); 33 | // Fall through. 34 | } 35 | res => { 36 | res?; 37 | return Ok((AnonPipe(FileDesc::new(fds[0])), 38 | AnonPipe(FileDesc::new(fds[1])))); 39 | } 40 | } 41 | } 42 | cvt(unsafe { linux::pipe(fds.as_mut_ptr()) })?; 43 | let fd0 = FileDesc::new(fds[0]); 44 | let fd1 = FileDesc::new(fds[1]); 45 | fd0.set_cloexec()?; 46 | fd1.set_cloexec()?; 47 | Ok((AnonPipe(fd0), AnonPipe(fd1))) 48 | } 49 | 50 | impl AnonPipe { 51 | pub fn read(&self, buf: &mut [u8]) -> io::Result { 52 | self.0.read(buf) 53 | } 54 | 55 | pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { 56 | self.0.read_to_end(buf) 57 | } 58 | 59 | pub fn write(&self, buf: &[u8]) -> io::Result { 60 | self.0.write(buf) 61 | } 62 | 63 | pub fn fd(&self) -> &FileDesc { &self.0 } 64 | pub fn into_fd(self) -> FileDesc { self.0 } 65 | } 66 | -------------------------------------------------------------------------------- /src/sys/linux/rand.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | pub use self::imp::OsRng; 12 | 13 | use mem; 14 | 15 | fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 { 16 | let mut buf: [u8; 4] = [0; 4]; 17 | fill_buf(&mut buf); 18 | unsafe { mem::transmute::<[u8; 4], u32>(buf) } 19 | } 20 | 21 | fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 { 22 | let mut buf: [u8; 8] = [0; 8]; 23 | fill_buf(&mut buf); 24 | unsafe { mem::transmute::<[u8; 8], u64>(buf) } 25 | } 26 | 27 | mod imp { 28 | use self::OsRngInner::*; 29 | use super::{next_u32, next_u64}; 30 | 31 | use ctypes::{c_char, ssize_t}; 32 | use fs::File; 33 | use io::{self, ErrorKind}; 34 | use linux::{self, errno}; 35 | use rand::Rng; 36 | use rand::reader::ReaderRng; 37 | use sys::cvtu; 38 | 39 | fn getrandom(buf: &mut [u8]) -> ssize_t { 40 | unsafe { 41 | linux::getrandom(buf.as_mut_ptr() as *mut c_char, 42 | buf.len(), 43 | linux::GRND_NONBLOCK) 44 | } 45 | } 46 | 47 | fn getrandom_fill_bytes(v: &mut [u8]) { 48 | let mut read = 0; 49 | while read < v.len() { 50 | match cvtu(getrandom(&mut v[read..])) { 51 | Err(e) => { 52 | let kind = e.kind(); 53 | if kind == ErrorKind::Interrupted { 54 | continue; 55 | } else if kind == ErrorKind::WouldBlock { 56 | // if getrandom() returns EAGAIN it would have blocked 57 | // because the non-blocking pool (urandom) has not 58 | // initialized in the kernel yet due to a lack of entropy 59 | // the fallback we do here is to avoid blocking applications 60 | // which could depend on this call without ever knowing 61 | // they do and don't have a work around. The PRNG of 62 | // /dev/urandom will still be used but not over a completely 63 | // full entropy pool 64 | let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom"); 65 | let mut reader_rng = ReaderRng::new(reader); 66 | reader_rng.fill_bytes(&mut v[read..]); 67 | read += v.len(); 68 | } else { 69 | panic!("unexpected getrandom error: {}", e); 70 | } 71 | } 72 | Ok(result) => read += result, 73 | } 74 | } 75 | } 76 | 77 | fn is_getrandom_available() -> bool { 78 | use sync::atomic::{AtomicUsize, Ordering}; 79 | 80 | const GETRANDOM_UNKNOWN: usize = 0; 81 | const GETRANDOM_AVAILABLE: usize = 1; 82 | const GETRANDOM_UNAVAILABLE: usize = 2; 83 | 84 | static AVAILABLE: AtomicUsize = AtomicUsize::new(GETRANDOM_UNKNOWN); 85 | 86 | match AVAILABLE.load(Ordering::Relaxed) { 87 | GETRANDOM_AVAILABLE => return true, 88 | GETRANDOM_UNAVAILABLE => return false, 89 | _ => {}, 90 | } 91 | 92 | let mut buf: [u8; 0] = []; 93 | let result = cvtu(getrandom(&mut buf)); 94 | let available = match result { 95 | Ok(_) => true, 96 | Err(e) => e.raw_os_error() != Some(errno::ENOSYS), 97 | }; 98 | 99 | AVAILABLE.store(if available { 100 | GETRANDOM_AVAILABLE 101 | } else { 102 | GETRANDOM_UNAVAILABLE 103 | }, Ordering::Relaxed); 104 | 105 | available 106 | } 107 | 108 | pub struct OsRng { 109 | inner: OsRngInner, 110 | } 111 | 112 | enum OsRngInner { 113 | OsGetrandomRng, 114 | OsReaderRng(ReaderRng), 115 | } 116 | 117 | impl OsRng { 118 | /// Create a new `OsRng`. 119 | pub fn new() -> io::Result { 120 | if is_getrandom_available() { 121 | return Ok(OsRng { inner: OsGetrandomRng }); 122 | } 123 | 124 | let reader = File::open("/dev/urandom")?; 125 | let reader_rng = ReaderRng::new(reader); 126 | 127 | Ok(OsRng { inner: OsReaderRng(reader_rng) }) 128 | } 129 | } 130 | 131 | impl Rng for OsRng { 132 | fn next_u32(&mut self) -> u32 { 133 | match self.inner { 134 | OsGetrandomRng => next_u32(&mut getrandom_fill_bytes), 135 | OsReaderRng(ref mut rng) => rng.next_u32(), 136 | } 137 | } 138 | fn next_u64(&mut self) -> u64 { 139 | match self.inner { 140 | OsGetrandomRng => next_u64(&mut getrandom_fill_bytes), 141 | OsReaderRng(ref mut rng) => rng.next_u64(), 142 | } 143 | } 144 | fn fill_bytes(&mut self, v: &mut [u8]) { 145 | match self.inner { 146 | OsGetrandomRng => getrandom_fill_bytes(v), 147 | OsReaderRng(ref mut rng) => rng.fill_bytes(v) 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/sys/linux/stack_overflow.rs: -------------------------------------------------------------------------------- 1 | pub struct Handler(()); 2 | 3 | impl Handler { 4 | pub unsafe fn new() -> Handler { 5 | // TODO(steed, #132): Implement a stack overflow handler. 6 | Handler(()) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/sys/linux/time.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use cmp::Ordering; 12 | use time::Duration; 13 | use linux; 14 | use ctypes::c_long; 15 | 16 | pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; 17 | 18 | const NSEC_PER_SEC: u64 = 1_000_000_000; 19 | 20 | #[derive(Copy, Clone)] 21 | struct Timespec { 22 | t: linux::timespec, 23 | } 24 | 25 | impl Timespec { 26 | fn sub_timespec(&self, other: &Timespec) -> Result { 27 | if self >= other { 28 | Ok(if self.t.tv_nsec >= other.t.tv_nsec { 29 | Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, 30 | (self.t.tv_nsec - other.t.tv_nsec) as u32) 31 | } else { 32 | Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, 33 | self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - 34 | other.t.tv_nsec as u32) 35 | }) 36 | } else { 37 | match other.sub_timespec(self) { 38 | Ok(d) => Err(d), 39 | Err(d) => Ok(d), 40 | } 41 | } 42 | } 43 | 44 | fn add_duration(&self, other: &Duration) -> Timespec { 45 | let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); 46 | let mut secs = secs.expect("overflow when adding duration to time"); 47 | 48 | // Nano calculations can't overflow because nanos are <1B which fit 49 | // in a u32. 50 | let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; 51 | if nsec >= NSEC_PER_SEC as u32 { 52 | nsec -= NSEC_PER_SEC as u32; 53 | secs = secs.checked_add(1).expect("overflow when adding \ 54 | duration to time"); 55 | } 56 | Timespec { 57 | t: linux::timespec { 58 | tv_sec: secs as linux::time_t, 59 | tv_nsec: nsec as c_long, 60 | }, 61 | } 62 | } 63 | 64 | fn sub_duration(&self, other: &Duration) -> Timespec { 65 | let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); 66 | let mut secs = secs.expect("overflow when subtracting duration \ 67 | from time"); 68 | 69 | // Similar to above, nanos can't overflow. 70 | let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; 71 | if nsec < 0 { 72 | nsec += NSEC_PER_SEC as i32; 73 | secs = secs.checked_sub(1).expect("overflow when subtracting \ 74 | duration from time"); 75 | } 76 | Timespec { 77 | t: linux::timespec { 78 | tv_sec: secs as linux::time_t, 79 | tv_nsec: c_long::from(nsec), 80 | }, 81 | } 82 | } 83 | } 84 | 85 | impl PartialEq for Timespec { 86 | fn eq(&self, other: &Timespec) -> bool { 87 | self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec 88 | } 89 | } 90 | 91 | impl Eq for Timespec {} 92 | 93 | impl PartialOrd for Timespec { 94 | fn partial_cmp(&self, other: &Timespec) -> Option { 95 | Some(self.cmp(other)) 96 | } 97 | } 98 | 99 | impl Ord for Timespec { 100 | fn cmp(&self, other: &Timespec) -> Ordering { 101 | let me = (self.t.tv_sec, self.t.tv_nsec); 102 | let other = (other.t.tv_sec, other.t.tv_nsec); 103 | me.cmp(&other) 104 | } 105 | } 106 | 107 | mod inner { 108 | use fmt; 109 | use linux; 110 | use time::Duration; 111 | 112 | use super::Timespec; 113 | 114 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 115 | pub struct Instant { 116 | t: Timespec, 117 | } 118 | 119 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 120 | pub struct SystemTime { 121 | t: Timespec, 122 | } 123 | 124 | pub const UNIX_EPOCH: SystemTime = SystemTime { 125 | t: Timespec { 126 | t: linux::timespec { 127 | tv_sec: 0, 128 | tv_nsec: 0, 129 | }, 130 | }, 131 | }; 132 | 133 | impl Instant { 134 | pub fn now() -> Instant { 135 | Instant { t: now(linux::CLOCK_MONOTONIC) } 136 | } 137 | 138 | pub fn sub_instant(&self, other: &Instant) -> Duration { 139 | self.t.sub_timespec(&other.t).unwrap_or_else(|_| { 140 | panic!("other was less than the current instant") 141 | }) 142 | } 143 | 144 | pub fn add_duration(&self, other: &Duration) -> Instant { 145 | Instant { t: self.t.add_duration(other) } 146 | } 147 | 148 | pub fn sub_duration(&self, other: &Duration) -> Instant { 149 | Instant { t: self.t.sub_duration(other) } 150 | } 151 | } 152 | 153 | impl fmt::Debug for Instant { 154 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 155 | f.debug_struct("Instant") 156 | .field("tv_sec", &self.t.t.tv_sec) 157 | .field("tv_nsec", &self.t.t.tv_nsec) 158 | .finish() 159 | } 160 | } 161 | 162 | impl SystemTime { 163 | pub fn now() -> SystemTime { 164 | SystemTime { t: now(linux::CLOCK_REALTIME) } 165 | } 166 | 167 | pub fn sub_time(&self, other: &SystemTime) 168 | -> Result { 169 | self.t.sub_timespec(&other.t) 170 | } 171 | 172 | pub fn add_duration(&self, other: &Duration) -> SystemTime { 173 | SystemTime { t: self.t.add_duration(other) } 174 | } 175 | 176 | pub fn sub_duration(&self, other: &Duration) -> SystemTime { 177 | SystemTime { t: self.t.sub_duration(other) } 178 | } 179 | } 180 | 181 | impl From for SystemTime { 182 | fn from(t: linux::timespec) -> SystemTime { 183 | SystemTime { t: Timespec { t: t } } 184 | } 185 | } 186 | 187 | impl fmt::Debug for SystemTime { 188 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 189 | f.debug_struct("SystemTime") 190 | .field("tv_sec", &self.t.t.tv_sec) 191 | .field("tv_nsec", &self.t.t.tv_nsec) 192 | .finish() 193 | } 194 | } 195 | 196 | fn now(clock: linux::clockid_t) -> Timespec { 197 | let mut t = Timespec { 198 | t: linux::timespec { 199 | tv_sec: 0, 200 | tv_nsec: 0, 201 | } 202 | }; 203 | // TODO issue #10 204 | // cvt(clock_gettime.unwrap()) 205 | unsafe { 206 | assert_eq!(linux::clock_gettime(clock, &mut t.t), 0) 207 | } 208 | t 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/sys/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Platform-dependent platform abstraction 12 | //! 13 | //! The `std::sys` module is the abstracted interface through which 14 | //! `std` talks to the underlying operating system. It has different 15 | //! implementations for different operating system families, today 16 | //! just Unix and Windows. 17 | //! 18 | //! The centralization of platform-specific code in this module is 19 | //! enforced by the "platform abstraction layer" tidy script in 20 | //! `tools/tidy/pal.rs`. 21 | //! 22 | //! This module is closely related to the platform-independent system 23 | //! integration code in `std::sys_common`. See that module's 24 | //! documentation for details. 25 | //! 26 | //! In the future it would be desirable for the indepedent 27 | //! implementations of this module to be extracted to their own crates 28 | //! that `std` can link to, thus enabling their implementation 29 | //! out-of-tree via crate replacement. Though due to the complex 30 | //! inter-dependencies within `std` that will be a challenging goal to 31 | //! achieve. 32 | 33 | pub use self::imp::*; 34 | 35 | #[path = "linux/mod.rs"] 36 | mod imp; 37 | -------------------------------------------------------------------------------- /src/sys_common/io.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | use io; 11 | use io::ErrorKind; 12 | use io::Read; 13 | use slice::from_raw_parts_mut; 14 | 15 | pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; 16 | 17 | // Provides read_to_end functionality over an uninitialized buffer. 18 | // This function is unsafe because it calls the underlying 19 | // read function with a slice into uninitialized memory. The default 20 | // implementation of read_to_end for readers will zero out new memory in 21 | // the buf before passing it to read, but avoiding this zero can often 22 | // lead to a fairly significant performance win. 23 | // 24 | // Implementations using this method have to adhere to two guarantees: 25 | // * The implementation of read never reads the buffer provided. 26 | // * The implementation of read correctly reports how many bytes were written. 27 | pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec) -> io::Result { 28 | 29 | let start_len = buf.len(); 30 | buf.reserve(16); 31 | 32 | // Always try to read into the empty space of the vector (from the length to the capacity). 33 | // If the vector ever fills up then we reserve an extra byte which should trigger the normal 34 | // reallocation routines for the vector, which will likely double the size. 35 | // 36 | // This function is similar to the read_to_end function in std::io, but the logic about 37 | // reservations and slicing is different enough that this is duplicated here. 38 | loop { 39 | if buf.len() == buf.capacity() { 40 | buf.reserve(1); 41 | } 42 | 43 | let buf_slice = from_raw_parts_mut(buf.as_mut_ptr().offset(buf.len() as isize), 44 | buf.capacity() - buf.len()); 45 | 46 | match r.read(buf_slice) { 47 | Ok(0) => { return Ok(buf.len() - start_len); } 48 | Ok(n) => { let len = buf.len() + n; buf.set_len(len); }, 49 | Err(ref e) if e.kind() == ErrorKind::Interrupted => { } 50 | Err(e) => { return Err(e); } 51 | } 52 | } 53 | } 54 | 55 | #[cfg(test)] 56 | #[allow(dead_code)] // not used on emscripten 57 | pub mod test { 58 | use path::{Path, PathBuf}; 59 | use env; 60 | use rand::{self, Rng}; 61 | use fs; 62 | 63 | pub struct TempDir(PathBuf); 64 | 65 | impl TempDir { 66 | pub fn join(&self, path: &str) -> PathBuf { 67 | let TempDir(ref p) = *self; 68 | p.join(path) 69 | } 70 | 71 | pub fn path<'a>(&'a self) -> &'a Path { 72 | let TempDir(ref p) = *self; 73 | p 74 | } 75 | } 76 | 77 | impl Drop for TempDir { 78 | fn drop(&mut self) { 79 | // Gee, seeing how we're testing the fs module I sure hope that we 80 | // at least implement this correctly! 81 | let TempDir(ref p) = *self; 82 | fs::remove_dir_all(p).unwrap(); 83 | } 84 | } 85 | 86 | pub fn tmpdir() -> TempDir { 87 | let p = env::temp_dir(); 88 | let mut r = rand::thread_rng(); 89 | let ret = p.join(&format!("rust-{}", r.next_u32())); 90 | fs::create_dir(&ret).unwrap(); 91 | TempDir(ret) 92 | } 93 | } 94 | 95 | #[cfg(test)] 96 | mod tests { 97 | use io::prelude::*; 98 | use super::*; 99 | use io; 100 | use io::{ErrorKind, Take, Repeat, repeat}; 101 | use slice::from_raw_parts; 102 | 103 | struct ErrorRepeat { 104 | lr: Take 105 | } 106 | 107 | fn error_repeat(byte: u8, limit: u64) -> ErrorRepeat { 108 | ErrorRepeat { lr: repeat(byte).take(limit) } 109 | } 110 | 111 | impl Read for ErrorRepeat { 112 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 113 | let ret = self.lr.read(buf); 114 | if let Ok(0) = ret { 115 | return Err(io::Error::new(ErrorKind::Other, "")) 116 | } 117 | ret 118 | } 119 | } 120 | 121 | fn init_vec_data() -> Vec { 122 | let mut vec = vec![10u8; 200]; 123 | unsafe { vec.set_len(0); } 124 | vec 125 | } 126 | 127 | fn assert_all_eq(buf: &[u8], value: u8) { 128 | for n in buf { 129 | assert_eq!(*n, value); 130 | } 131 | } 132 | 133 | fn validate(buf: &Vec, good_read_len: usize) { 134 | assert_all_eq(buf, 1u8); 135 | let cap = buf.capacity(); 136 | let end_slice = unsafe { from_raw_parts(buf.as_ptr().offset(good_read_len as isize), 137 | cap - good_read_len) }; 138 | assert_all_eq(end_slice, 10u8); 139 | } 140 | 141 | #[test] 142 | fn read_to_end_uninit_error() { 143 | let mut er = error_repeat(1,100); 144 | let mut vec = init_vec_data(); 145 | if let Err(_) = unsafe { read_to_end_uninitialized(&mut er, &mut vec) } { 146 | validate(&vec, 100); 147 | } else { 148 | assert!(false); 149 | } 150 | } 151 | 152 | #[test] 153 | fn read_to_end_uninit_zero_len_vec() { 154 | let mut er = repeat(1).take(100); 155 | let mut vec = Vec::new(); 156 | let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; 157 | assert_all_eq(&vec, 1u8); 158 | assert_eq!(vec.len(), n); 159 | } 160 | 161 | #[test] 162 | fn read_to_end_uninit_good() { 163 | let mut er = repeat(1).take(100); 164 | let mut vec = init_vec_data(); 165 | let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; 166 | validate(&vec, 100); 167 | assert_eq!(vec.len(), n); 168 | } 169 | 170 | #[bench] 171 | #[cfg_attr(target_os = "emscripten", ignore)] 172 | fn bench_uninitialized(b: &mut ::test::Bencher) { 173 | b.iter(|| { 174 | let mut lr = repeat(1).take(10000000); 175 | let mut vec = Vec::with_capacity(1024); 176 | unsafe { read_to_end_uninitialized(&mut lr, &mut vec) } 177 | }); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/sys_common/mod.rs: -------------------------------------------------------------------------------- 1 | // Rust 1.16.0 (no tests) 2 | pub mod io; 3 | // Rust 1.16.0 4 | pub mod mutex; 5 | // Rust 1.16.0 (no tests, missing support for `lookup_host`) 6 | pub mod net; 7 | // Rust 1.16.0 8 | pub mod poison; 9 | // Rust 1.15.0 10 | pub mod thread; 11 | 12 | pub mod util; 13 | 14 | /// A trait for viewing representations from std types 15 | #[doc(hidden)] 16 | pub trait AsInner { 17 | fn as_inner(&self) -> &Inner; 18 | } 19 | 20 | /// A trait for viewing representations from std types 21 | #[doc(hidden)] 22 | pub trait AsInnerMut { 23 | fn as_inner_mut(&mut self) -> &mut Inner; 24 | } 25 | 26 | /// A trait for extracting representations from std types 27 | #[doc(hidden)] 28 | pub trait IntoInner { 29 | fn into_inner(self) -> Inner; 30 | } 31 | 32 | /// A trait for creating std types from internal representations 33 | #[doc(hidden)] 34 | pub trait FromInner { 35 | fn from_inner(inner: Inner) -> Self; 36 | } 37 | 38 | /// One-time runtime cleanup. 39 | pub fn cleanup() { } 40 | -------------------------------------------------------------------------------- /src/sys_common/mutex.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use sys::mutex as imp; 12 | 13 | /// An OS-based mutual exclusion lock. 14 | /// 15 | /// This is the thinnest cross-platform wrapper around OS mutexes. All usage of 16 | /// this mutex is unsafe and it is recommended to instead use the safe wrapper 17 | /// at the top level of the crate instead of this type. 18 | pub struct Mutex(imp::Mutex); 19 | 20 | unsafe impl Sync for Mutex {} 21 | 22 | impl Mutex { 23 | /// Creates a new mutex for use. 24 | /// 25 | /// Behavior is undefined if the mutex is moved after it is 26 | /// first used with any of the functions below. 27 | pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) } 28 | 29 | /// Prepare the mutex for use. 30 | /// 31 | /// This should be called once the mutex is at a stable memory address. 32 | #[inline] 33 | pub unsafe fn init(&mut self) { self.0.init() } 34 | 35 | /// Locks the mutex blocking the current thread until it is available. 36 | /// 37 | /// Behavior is undefined if the mutex has been moved between this and any 38 | /// previous function call. 39 | #[inline] 40 | pub unsafe fn lock(&self) { self.0.lock() } 41 | 42 | /// Attempts to lock the mutex without blocking, returning whether it was 43 | /// successfully acquired or not. 44 | /// 45 | /// Behavior is undefined if the mutex has been moved between this and any 46 | /// previous function call. 47 | #[inline] 48 | pub unsafe fn try_lock(&self) -> bool { self.0.try_lock() } 49 | 50 | /// Unlocks the mutex. 51 | /// 52 | /// Behavior is undefined if the current thread does not actually hold the 53 | /// mutex. 54 | #[inline] 55 | pub unsafe fn unlock(&self) { self.0.unlock() } 56 | 57 | /// Deallocates all resources associated with this mutex. 58 | /// 59 | /// Behavior is undefined if there are current or will be future users of 60 | /// this mutex. 61 | #[inline] 62 | pub unsafe fn destroy(&self) { self.0.destroy() } 63 | } 64 | 65 | // not meant to be exported to the outside world, just the containing module 66 | pub fn raw(mutex: &Mutex) -> &imp::Mutex { &mutex.0 } 67 | -------------------------------------------------------------------------------- /src/sys_common/thread.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use alloc::boxed::FnBox; 12 | use libc; 13 | use sys::stack_overflow; 14 | 15 | pub unsafe fn start_thread(main: *mut libc::c_void) { 16 | // Next, set up our stack overflow handler which may get triggered if we run 17 | // out of stack. 18 | let _handler = stack_overflow::Handler::new(); 19 | 20 | // Finally, let's run some code. 21 | Box::from_raw(main as *mut Box)() 22 | } 23 | -------------------------------------------------------------------------------- /src/sys_common/util.rs: -------------------------------------------------------------------------------- 1 | pub fn min_stack() -> usize { 2 | 2 * 1024 * 1024 + 1 3 | } 4 | -------------------------------------------------------------------------------- /test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Jorge Aparicio "] 3 | name = "test" 4 | version = "0.1.0" 5 | -------------------------------------------------------------------------------- /test/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use self::TestFn::*; 2 | 3 | pub mod test { 4 | pub use ShouldPanic; 5 | } 6 | 7 | pub struct TestDesc { 8 | pub allow_fail: bool, 9 | pub ignore: bool, 10 | pub name: StaticTestName, 11 | pub should_panic: ShouldPanic, 12 | } 13 | 14 | pub struct TestDescAndFn { 15 | pub desc: TestDesc, 16 | pub testfn: TestFn, 17 | } 18 | 19 | pub enum TestFn { 20 | StaticBenchFn(fn(&mut Bencher)), 21 | StaticTestFn(fn()), 22 | } 23 | 24 | pub struct StaticTestName(pub &'static str); 25 | 26 | pub struct Bencher {} 27 | 28 | impl Bencher { 29 | pub fn iter(&mut self, _: F) where F: FnMut() -> T {} 30 | } 31 | 32 | #[derive(Clone, Copy)] 33 | pub enum ShouldPanic { 34 | No, 35 | Yes, 36 | } 37 | 38 | pub fn black_box(_: T) {} 39 | 40 | pub fn test_main_static(tests: &'static [TestDescAndFn]) { 41 | let n = tests.len(); 42 | 43 | println!("Running {} test{}", n, if n == 1 { "" } else { "s" }); 44 | 45 | let mut passed = 0; 46 | let mut ignored = 0; 47 | for test in tests { 48 | match (test.desc.should_panic, &test.testfn) { 49 | (ShouldPanic::No, &TestFn::StaticTestFn(ref f)) => { 50 | print!("test {} ... ", test.desc.name.0); 51 | f(); 52 | println!("ok"); 53 | passed += 1; 54 | } 55 | _ => { 56 | println!("test {} ... ignored", test.desc.name.0); 57 | ignored += 1; 58 | } 59 | } 60 | } 61 | 62 | println!("\ntest result: ok. {} passed; 0 failed; {} ignored; 0 measured", 63 | passed, 64 | ignored); 65 | } 66 | --------------------------------------------------------------------------------