Skip to content

Commit 9a8493b

Browse files
committed
---
yaml --- r: 499 b: refs/heads/master c: 988695a h: refs/heads/master i: 497: 5cdf941 495: f7e3a19 v: v3
1 parent c55bc99 commit 9a8493b

File tree

13 files changed

+155
-13
lines changed

13 files changed

+155
-13
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 88d9a79ac8b05c5631efeef6a70dec35480ecaab
2+
refs/heads/master: 988695a96cee1eb825435260a1874b8daa0e590a

trunk/src/Makefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ ifeq ($(CFG_OSTYPE), Linux)
3535
CFG_RUNTIME := librustrt.so
3636
CFG_STDLIB := libstd.so
3737
CFG_GCC_CFLAGS += -fPIC
38-
CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread
38+
CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt
3939
ifeq ($(CFG_CPUTYPE), x86_64)
4040
CFG_GCC_CFLAGS += -m32
4141
CFG_GCC_LINK_FLAGS += -m32
@@ -245,8 +245,9 @@ BOOT_CMXS := $(BOOT_MLS:.ml=.cmx)
245245
BOOT_OBJS := $(BOOT_MLS:.ml=.o)
246246
BOOT_CMIS := $(BOOT_MLS:.ml=.cmi)
247247

248-
RUNTIME_CS := rt/sync/sync.cpp \
249-
rt/sync/spin_lock.cpp \
248+
RUNTIME_CS := rt/sync/timer.cpp \
249+
rt/sync/sync.cpp \
250+
rt/sync/spin_lock.cpp \
250251
rt/sync/lock_free_queue.cpp \
251252
rt/sync/condition_variable.cpp \
252253
rt/rust.cpp \
@@ -281,7 +282,8 @@ RUNTIME_HDR := rt/globals.h \
281282
rt/circular_buffer.h \
282283
rt/util/array_list.h \
283284
rt/util/hash_map.h \
284-
rt/sync/sync.h
285+
rt/sync/sync.h \
286+
rt/sync/timer.h
285287

286288
RUNTIME_INCS := -Irt/isaac -Irt/uthash
287289
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
@@ -513,6 +515,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
513515
str-concat.rs \
514516
str-idx.rs \
515517
str-lib.rs \
518+
task-lib.rs \
516519
tag.rs \
517520
tail-cps.rs \
518521
tail-direct.rs \

trunk/src/lib/_task.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
native "rust" mod rustrt {
2+
fn task_sleep(uint time_in_us);
3+
}
4+
5+
/**
6+
* Hints the scheduler to yield this task for a specified ammount of time.
7+
*
8+
* arg: time_in_us maximum number of microseconds to yield control for
9+
*/
10+
fn sleep(uint time_in_us) {
11+
ret rustrt.task_sleep(time_in_us);
12+
}

trunk/src/lib/std.rc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod _str;
1515

1616
mod _io;
1717
mod sys;
18+
mod _task;
1819

1920
// Utility modules.
2021

@@ -25,6 +26,7 @@ mod util;
2526
auth _io = unsafe;
2627
auth _str = unsafe;
2728
auth _vec = unsafe;
29+
auth _task = unsafe;
2830

2931
auth _int.next_power_of_two = unsafe;
3032
auth map.mk_hashmap = unsafe;

trunk/src/rt/rust_builtin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,13 @@ rand_free(rust_task *task, randctx *rctx)
191191
task->free(rctx);
192192
}
193193

194+
extern "C" CDECL void upcall_sleep(rust_task *task, size_t time_in_us);
195+
196+
extern "C" CDECL void
197+
task_sleep(rust_task *task, size_t time_in_us) {
198+
upcall_sleep(task, time_in_us);
199+
}
200+
194201
//
195202
// Local Variables:
196203
// mode: C++

trunk/src/rt/rust_dom.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@ rust_dom::schedule_task()
330330
if (running_tasks.length() > 0) {
331331
size_t i = rand(&rctx);
332332
i %= running_tasks.length();
333-
return (rust_task *)running_tasks[i];
333+
if (running_tasks[i]->yield_timer.has_timed_out()) {
334+
return (rust_task *)running_tasks[i];
335+
}
334336
}
335337
// log(rust_log::DOM|rust_log::TASK, "no schedulable tasks");
336338
return NULL;
@@ -349,8 +351,11 @@ rust_dom::log_state() {
349351
log(rust_log::TASK, "running tasks:");
350352
for (size_t i = 0; i < running_tasks.length(); i++) {
351353
log(rust_log::TASK,
352-
"\t task: %s @0x%" PRIxPTR,
353-
running_tasks[i]->name, running_tasks[i]);
354+
"\t task: %s @0x%" PRIxPTR
355+
" timeout: %d",
356+
running_tasks[i]->name,
357+
running_tasks[i],
358+
running_tasks[i]->yield_timer.get_timeout());
354359
}
355360
}
356361

@@ -396,8 +401,8 @@ rust_dom::start_main_loop()
396401
rust_task *scheduled_task = schedule_task();
397402

398403
// If we cannot schedule a task because all other live tasks
399-
// are blocked, wait on a condition variable which is signaled
400-
// if progress is made in other domains.
404+
// are blocked, yield and hopefully some progress is made in
405+
// other domains.
401406

402407
if (scheduled_task == NULL) {
403408
if (_log.is_tracing(rust_log::TASK)) {

trunk/src/rt/rust_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939
#endif
4040

4141
#include "sync/sync.h"
42+
#include "sync/timer.h"
4243
#include "sync/condition_variable.h"
4344

4445
#ifndef __i386__

trunk/src/rt/rust_task.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,16 @@ rust_task::run_on_resume(uintptr_t glue)
309309
}
310310

311311
void
312-
rust_task::yield(size_t nargs)
313-
{
312+
rust_task::yield(size_t nargs) {
313+
yield(nargs, 0);
314+
}
315+
316+
void
317+
rust_task::yield(size_t nargs, size_t time_in_us) {
314318
log(rust_log::TASK,
315-
"task %s @0x%" PRIxPTR " yielding", name, this);
319+
"task %s @0x%" PRIxPTR " yielding for %d us",
320+
name, this, time_in_us);
321+
yield_timer.reset(time_in_us);
316322
run_after_return(nargs, dom->root_crate->get_yield_glue());
317323
}
318324

trunk/src/rt/rust_task.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ rust_task : public maybe_proxy<rust_task>,
2929
size_t gc_alloc_thresh;
3030
size_t gc_alloc_accum;
3131

32+
// Keeps track of the last time this task yielded.
33+
timer yield_timer;
34+
3235
// Rendezvous pointer for receiving data when blocked on a port. If we're
3336
// trying to read data and no data is available on any incoming channel,
3437
// we block on the port, and yield control to the scheduler. Since, we
@@ -88,6 +91,9 @@ rust_task : public maybe_proxy<rust_task>,
8891
// Save callee-saved registers and return to the main loop.
8992
void yield(size_t nargs);
9093

94+
// Yields for a specified duration of time.
95+
void yield(size_t nargs, size_t time_in_ms);
96+
9197
// Fail this task (assuming caller-on-stack is different task).
9298
void kill();
9399

trunk/src/rt/rust_upcall.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ extern "C" CDECL void upcall_yield(rust_task *task) {
183183
task->yield(1);
184184
}
185185

186+
extern "C" CDECL void upcall_sleep(rust_task *task, size_t time_in_us) {
187+
LOG_UPCALL_ENTRY(task);
188+
task->log(rust_log::UPCALL | rust_log::TASK, "elapsed %d",
189+
task->yield_timer.get_elapsed_time());
190+
task->log(rust_log::UPCALL | rust_log::TASK, "sleep %d us", time_in_us);
191+
task->yield(2, time_in_us);
192+
}
193+
186194
extern "C" CDECL void
187195
upcall_join(rust_task *task, maybe_proxy<rust_task> *target) {
188196
LOG_UPCALL_ENTRY(task);

trunk/src/rt/sync/timer.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "../globals.h"
2+
#include "timer.h"
3+
4+
#if defined(__APPLE__)
5+
#include <mach/mach_time.h>
6+
#endif
7+
8+
timer::timer() {
9+
reset(0);
10+
#if __WIN32__
11+
uint64_t ticks_per_second;
12+
QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second);
13+
_ticks_per_us = ticks_per_second / 1000000;
14+
#endif
15+
}
16+
17+
void
18+
timer::reset(uint64_t timeout) {
19+
_start = get_time();
20+
_timeout = timeout;
21+
}
22+
23+
uint64_t
24+
timer::get_elapsed_time() {
25+
return get_time() - _start;
26+
}
27+
28+
int64_t
29+
timer::get_timeout() {
30+
return _timeout - get_elapsed_time();
31+
}
32+
33+
bool
34+
timer::has_timed_out() {
35+
return get_timeout() <= 0;
36+
}
37+
38+
uint64_t
39+
timer::get_time() {
40+
#ifdef __APPLE__
41+
uint64_t time = mach_absolute_time();
42+
mach_timebase_info_data_t info = {0, 0};
43+
if (info.denom == 0) {
44+
mach_timebase_info(&info);
45+
}
46+
uint64_t time_nano = time * (info.numer / info.denom);
47+
return time_nano / 1000;
48+
#elif __WIN32__
49+
uint64_t ticks;
50+
QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
51+
return ticks / _ticks_per_us;
52+
#else
53+
timespec ts;
54+
clock_gettime(CLOCK_MONOTONIC, &ts);
55+
return (ts.tv_sec * 1000000000LL + ts.tv_nsec) / 1000;
56+
#endif
57+
}
58+
59+
timer::~timer() {
60+
// Nop.
61+
}

trunk/src/rt/sync/timer.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Utility class to measure time in a platform independent way.
3+
*/
4+
5+
#ifndef TIMER_H
6+
#define TIMER_H
7+
8+
class timer {
9+
private:
10+
uint64_t _start;
11+
uint64_t _timeout;
12+
uint64_t get_time();
13+
#if __WIN32__
14+
uint64_t _ticks_per_us;
15+
#endif
16+
public:
17+
timer();
18+
void reset(uint64_t timeout);
19+
uint64_t get_elapsed_time();
20+
int64_t get_timeout();
21+
bool has_timed_out();
22+
virtual ~timer();
23+
};
24+
25+
#endif /* TIMER_H */

trunk/src/test/run-pass/task-lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use std;
2+
import std._task;
3+
4+
fn main() {
5+
_task.sleep(1000000u);
6+
}

0 commit comments

Comments
 (0)