Skip to content

Commit 7476a39

Browse files
committed
stdlib: Implement some preliminary libuv bindings
std::uv is intended to be low-level, exactly mirroring the C API. Difficult to continue the implementation now without scheduler improvements.
1 parent b2fd612 commit 7476a39

File tree

9 files changed

+284
-2
lines changed

9 files changed

+284
-2
lines changed

mk/rt.mk

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ RUNTIME_CS_$(1) := \
4747
rt/rust_task_list.cpp \
4848
rt/rust_port.cpp \
4949
rt/rust_upcall.cpp \
50+
rt/rust_uv.cpp \
5051
rt/rust_log.cpp \
5152
rt/rust_timer.cpp \
5253
rt/circular_buffer.cpp \

src/etc/x86.supp

+23
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,26 @@
364364
fun:_Znwj
365365
fun:_ZN4llvm4UsernwEjj
366366
}
367+
368+
{
369+
libuv-0-byte-realloc1
370+
Memcheck:Leak
371+
fun:malloc
372+
fun:realloc
373+
fun:ev_realloc_emul
374+
fun:ev_realloc
375+
fun:epoll_destroy
376+
fun:ev_loop_destroy
377+
fun:uv_loop_delete
378+
}
379+
380+
{
381+
libuv-0-byte-realloc2
382+
Memcheck:Leak
383+
fun:malloc
384+
fun:realloc
385+
fun:ev_realloc_emul
386+
fun:ev_realloc
387+
fun:ev_loop_destroy
388+
fun:uv_loop_delete
389+
}

src/lib/ctypes.rs

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Definitions useful for C interop
66

77
type c_int = i32;
88

9+
type void = int; // Not really the same as C
910
type long = int;
1011
type unsigned = u32;
1112
type ulong = uint;
@@ -23,3 +24,6 @@ type off_t = uint;
2324

2425
type fd_t = i32; // not actually a C type, but should be.
2526
type pid_t = i32;
27+
28+
// enum is implementation-defined, but is 32-bits in practice
29+
type enum = u32;

src/lib/std.rc

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
export box, char, float, int, str, ptr;
1111
export uint, u8, u32, u64, vec, bool;
12-
export comm, fs, io, net, run, sys, task;
12+
export comm, fs, io, net, run, sys, task, uv;
1313
export c_vec, ctypes, either, option, result, four, tri, util;
1414
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
1515
export rope;
@@ -46,6 +46,7 @@ mod net;
4646
mod run;
4747
mod sys;
4848
mod task;
49+
mod uv;
4950

5051

5152
// Utility modules

src/lib/uv.rs

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
This is intended to be a low-level binding to libuv that very closely mimics
3+
the C libuv API. Does very little right now pending scheduler improvements.
4+
*/
5+
6+
#[cfg(target_os = "linux")];
7+
#[cfg(target_os = "macos")];
8+
9+
export sanity_check;
10+
export loop_t, idle_t;
11+
export loop_new, loop_delete, default_loop, run, unref;
12+
export idle_init, idle_start;
13+
export idle_new;
14+
15+
#[link_name = "rustrt"]
16+
native mod uv {
17+
fn rust_uv_loop_new() -> *loop_t;
18+
fn rust_uv_loop_delete(loop: *loop_t);
19+
fn rust_uv_default_loop() -> *loop_t;
20+
fn rust_uv_run(loop: *loop_t) -> ctypes::c_int;
21+
fn rust_uv_unref(loop: *loop_t);
22+
fn rust_uv_idle_init(loop: *loop_t, idle: *idle_t) -> ctypes::c_int;
23+
fn rust_uv_idle_start(idle: *idle_t, cb: idle_cb) -> ctypes::c_int;
24+
}
25+
26+
#[link_name = "rustrt"]
27+
native mod helpers {
28+
fn rust_uv_size_of_idle_t() -> ctypes::size_t;
29+
}
30+
31+
type opaque_cb = *ctypes::void;
32+
33+
type handle_type = ctypes::enum;
34+
35+
type close_cb = opaque_cb;
36+
type idle_cb = opaque_cb;
37+
38+
#[cfg(target_os = "linux")]
39+
#[cfg(target_os = "macos")]
40+
type handle_private_fields = {
41+
a00: ctypes::c_int,
42+
a01: ctypes::c_int,
43+
a02: ctypes::c_int,
44+
a03: ctypes::c_int,
45+
a04: ctypes::c_int,
46+
a05: ctypes::c_int,
47+
a06: int,
48+
a07: int,
49+
a08: int,
50+
a09: int,
51+
a10: int,
52+
a11: int,
53+
a12: int
54+
};
55+
56+
type handle_fields = {
57+
loop: *loop_t,
58+
type_: handle_type,
59+
close_cb: close_cb,
60+
data: *ctypes::void,
61+
private: handle_private_fields
62+
};
63+
64+
type handle_t = {
65+
fields: handle_fields
66+
};
67+
68+
type loop_t = int;
69+
70+
71+
72+
73+
type idle_t = {
74+
fields: handle_fields
75+
/* private: idle_private_fields */
76+
};
77+
78+
fn idle_init(loop: *loop_t, idle: *idle_t) -> ctypes::c_int {
79+
uv::rust_uv_idle_init(loop, idle)
80+
}
81+
82+
fn idle_start(idle: *idle_t, cb: idle_cb) -> ctypes::c_int {
83+
uv::rust_uv_idle_start(idle, cb)
84+
}
85+
86+
87+
88+
89+
fn default_loop() -> *loop_t {
90+
uv::rust_uv_default_loop()
91+
}
92+
93+
fn loop_new() -> *loop_t {
94+
uv::rust_uv_loop_new()
95+
}
96+
97+
fn loop_delete(loop: *loop_t) {
98+
uv::rust_uv_loop_delete(loop)
99+
}
100+
101+
fn run(loop: *loop_t) -> ctypes::c_int {
102+
uv::rust_uv_run(loop)
103+
}
104+
105+
fn unref(loop: *loop_t) {
106+
uv::rust_uv_unref(loop)
107+
}
108+
109+
110+
fn sanity_check() {
111+
fn check_size(t: str, uv: ctypes::size_t, rust: ctypes::size_t) {
112+
log #fmt("size of %s: uv: %u, rust: %u", t, uv, rust);
113+
assert uv == rust;
114+
}
115+
check_size("idle_t",
116+
helpers::rust_uv_size_of_idle_t(),
117+
sys::size_of::<idle_t>());
118+
}
119+
120+
#[cfg(target_os = "linux")]
121+
#[cfg(target_os = "macos")]
122+
fn handle_fields_new() -> handle_fields {
123+
{
124+
loop: ptr::null(),
125+
type_: 0u32,
126+
close_cb: ptr::null(),
127+
data: ptr::null(),
128+
private: {
129+
a00: 0i32,
130+
a01: 0i32,
131+
a02: 0i32,
132+
a03: 0i32,
133+
a04: 0i32,
134+
a05: 0i32,
135+
a06: 0,
136+
a07: 0,
137+
a08: 0,
138+
a09: 0,
139+
a10: 0,
140+
a11: 0,
141+
a12: 0
142+
}
143+
}
144+
}
145+
146+
fn idle_new() -> idle_t {
147+
{
148+
fields: handle_fields_new()
149+
}
150+
}

src/rt/rust_uv.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "rust_internal.h"
2+
#include "uv.h"
3+
4+
/*
5+
Wrappers of uv_* functions. These can be eliminated by figuring
6+
out how to build static uv with externs, or by just using dynamic libuv
7+
*/
8+
9+
extern "C" CDECL uv_loop_t*
10+
rust_uv_default_loop() {
11+
return uv_default_loop();
12+
}
13+
14+
extern "C" CDECL uv_loop_t*
15+
rust_uv_loop_new() {
16+
return uv_loop_new();
17+
}
18+
19+
extern "C" CDECL void
20+
rust_uv_loop_delete(uv_loop_t *loop) {
21+
return uv_loop_delete(loop);
22+
}
23+
24+
extern "C" CDECL int
25+
rust_uv_run(uv_loop_t *loop) {
26+
return uv_run(loop);
27+
}
28+
29+
extern "C" CDECL void
30+
rust_uv_unref(uv_loop_t *loop) {
31+
return uv_unref(loop);
32+
}
33+
34+
extern "C" CDECL int
35+
rust_uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
36+
return uv_idle_init(loop, idle);
37+
}
38+
39+
extern "C" CDECL int
40+
rust_uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
41+
return uv_idle_start(idle, cb);
42+
}
43+
44+
45+
46+
47+
extern "C" CDECL size_t
48+
rust_uv_size_of_idle_t() {
49+
return sizeof(uv_idle_t);
50+
}

src/rt/rustrt.def.in

+9-1
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,12 @@ upcall_vec_push
6868
upcall_call_shim_on_c_stack
6969
upcall_new_stack
7070
upcall_del_stack
71-
asm_call_on_stack
71+
asm_call_on_stack
72+
rust_uv_default_loop
73+
rust_uv_loop_new
74+
rust_uv_loop_delete
75+
rust_uv_run
76+
rust_uv_unref
77+
rust_uv_idle_init
78+
rust_uv_idle_start
79+
rust_uv_size_of_idle_t

src/test/stdtest/stdtest.rc

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ mod tri;
4040
mod treemap;
4141
mod uint;
4242
mod unsafe;
43+
mod uv;
4344
mod vec;
4445

4546
// Local Variables:

src/test/stdtest/uv.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#[cfg(target_os = "linux")];
2+
#[cfg(target_os = "macos")];
3+
4+
import std::uv;
5+
import std::ptr;
6+
7+
#[test]
8+
fn sanity_check() {
9+
uv::sanity_check();
10+
}
11+
12+
// From test-ref.c
13+
mod test_ref {
14+
15+
#[test]
16+
fn ref() {
17+
let loop = uv::loop_new();
18+
uv::run(loop);
19+
uv::loop_delete(loop);
20+
}
21+
22+
#[test]
23+
fn idle_ref() {
24+
let loop = uv::loop_new();
25+
let h = uv::idle_new();
26+
uv::idle_init(loop, ptr::addr_of(h));
27+
uv::idle_start(ptr::addr_of(h), ptr::null());
28+
uv::unref(loop);
29+
uv::run(loop);
30+
uv::loop_delete(loop);
31+
}
32+
33+
#[test]
34+
fn async_ref() {
35+
/*
36+
let loop = uv::loop_new();
37+
let h = uv::async_new();
38+
uv::async_init(loop, ptr::addr_of(h), ptr::null());
39+
uv::unref(loop);
40+
uv::run(loop);
41+
uv::loop_delete(loop);
42+
*/
43+
}
44+
}

0 commit comments

Comments
 (0)