mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-02 01:52:51 +00:00
Introduced task handles.
This is the new way to refer to tasks in rust-land. Currently all they do is serve as a key to look up the old rust_task structure. Ideally they won't be ref counted, but baby steps.
This commit is contained in:
parent
f4f057ced1
commit
44bef5f2cb
@ -4,7 +4,7 @@
|
||||
// NB: please do not commit code with this uncommented. It's
|
||||
// hugely expensive and should only be used as a last resort.
|
||||
//
|
||||
// #define TRACK_ALLOCATIONS
|
||||
#define TRACK_ALLOCATIONS
|
||||
|
||||
#define MAGIC 0xbadc0ffe
|
||||
|
||||
|
@ -93,7 +93,9 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
|
||||
|
||||
rust_srv *srv = new rust_srv(env);
|
||||
rust_kernel *kernel = new rust_kernel(srv, env->num_sched_threads);
|
||||
rust_task *root_task = kernel->create_task(NULL, "main");
|
||||
rust_task_id root_id = kernel->create_task(NULL, "main");
|
||||
rust_task *root_task = kernel->get_task_by_id(root_id);
|
||||
I(kernel, root_task != NULL);
|
||||
rust_scheduler *sched = root_task->sched;
|
||||
command_line_args *args
|
||||
= new (kernel, "main command line args")
|
||||
|
@ -408,8 +408,11 @@ task_yield(rust_task *task) {
|
||||
}
|
||||
|
||||
extern "C" CDECL intptr_t
|
||||
task_join(rust_task *task, rust_task *join_task) {
|
||||
task_join(rust_task *task, rust_task_id tid) {
|
||||
// If the other task is already dying, we don't have to wait for it.
|
||||
rust_task *join_task = task->kernel->get_task_by_id(tid);
|
||||
// FIXME: find task exit status and return that.
|
||||
if(!join_task) return 0;
|
||||
join_task->lock.lock();
|
||||
if (join_task->dead() == false) {
|
||||
join_task->tasks_waiting_to_join.push(task);
|
||||
|
@ -73,16 +73,17 @@ void rust_chan::disassociate() {
|
||||
* Attempt to send data to the associated port.
|
||||
*/
|
||||
void rust_chan::send(void *sptr) {
|
||||
scoped_lock with(port->lock);
|
||||
|
||||
buffer.enqueue(sptr);
|
||||
|
||||
if (!is_associated()) {
|
||||
W(kernel, is_associated(),
|
||||
"rust_chan::transmit with no associated port.");
|
||||
return;
|
||||
}
|
||||
|
||||
I(kernel, port != NULL);
|
||||
scoped_lock with(port->lock);
|
||||
|
||||
buffer.enqueue(sptr);
|
||||
|
||||
A(kernel, !buffer.is_empty(),
|
||||
"rust_chan::transmit with nothing to send.");
|
||||
|
||||
|
@ -64,6 +64,8 @@ struct stk_seg;
|
||||
struct type_desc;
|
||||
struct frame_glue_fns;
|
||||
|
||||
typedef intptr_t rust_task_id;
|
||||
|
||||
#ifndef __i386__
|
||||
#error "Target CPU not supported."
|
||||
#endif
|
||||
|
@ -9,6 +9,7 @@ rust_kernel::rust_kernel(rust_srv *srv, size_t num_threads) :
|
||||
_region(srv, true),
|
||||
_log(srv, NULL),
|
||||
srv(srv),
|
||||
max_id(0),
|
||||
num_threads(num_threads),
|
||||
rval(0),
|
||||
live_tasks(0),
|
||||
@ -133,10 +134,31 @@ int rust_kernel::start_task_threads()
|
||||
return rval;
|
||||
}
|
||||
|
||||
rust_task *
|
||||
rust_task_id
|
||||
rust_kernel::create_task(rust_task *spawner, const char *name) {
|
||||
rust_scheduler *thread = threads[rand(&rctx) % num_threads];
|
||||
return thread->create_task(spawner, name);
|
||||
rust_task *t = thread->create_task(spawner, name);
|
||||
{
|
||||
scoped_lock with(_kernel_lock);
|
||||
t->id = max_id++;
|
||||
task_table.put(t->id, t);
|
||||
}
|
||||
return t->id;
|
||||
}
|
||||
|
||||
rust_task *
|
||||
rust_kernel::get_task_by_id(rust_task_id id) {
|
||||
scoped_lock with(_kernel_lock);
|
||||
rust_task *task = NULL;
|
||||
// get leaves task unchanged if not found.
|
||||
task_table.get(id, &task);
|
||||
return task;
|
||||
}
|
||||
|
||||
void
|
||||
rust_kernel::release_task_id(rust_task_id id) {
|
||||
scoped_lock with(_kernel_lock);
|
||||
task_table.remove(id);
|
||||
}
|
||||
|
||||
void rust_kernel::wakeup_schedulers() {
|
||||
|
@ -26,8 +26,10 @@ private:
|
||||
void create_schedulers();
|
||||
void destroy_schedulers();
|
||||
|
||||
public:
|
||||
rust_task_id max_id;
|
||||
hash_map<rust_task_id, rust_task *> task_table;
|
||||
|
||||
public:
|
||||
const size_t num_threads;
|
||||
int rval;
|
||||
|
||||
@ -56,7 +58,9 @@ public:
|
||||
void win32_require(LPCTSTR fn, BOOL ok);
|
||||
#endif
|
||||
|
||||
rust_task *create_task(rust_task *spawner, const char *name);
|
||||
rust_task_id create_task(rust_task *spawner, const char *name);
|
||||
rust_task *get_task_by_id(rust_task_id id);
|
||||
void release_task_id(rust_task_id tid);
|
||||
};
|
||||
|
||||
#endif /* RUST_KERNEL_H */
|
||||
|
@ -51,9 +51,6 @@ struct rust_scheduler : public kernel_owned<rust_scheduler>,
|
||||
rust_kernel *kernel;
|
||||
int32_t list_index;
|
||||
|
||||
hash_map<rust_task *, rust_task *> _task_proxies;
|
||||
hash_map<rust_port *, rust_port *> _port_proxies;
|
||||
|
||||
const int id;
|
||||
|
||||
lock_and_signal lock;
|
||||
|
@ -95,6 +95,8 @@ rust_task::~rust_task()
|
||||
DLOG(sched, task, "~rust_task %s @0x%" PRIxPTR ", refcnt=%d",
|
||||
name, (uintptr_t)this, ref_count);
|
||||
|
||||
kernel->release_task_id(id);
|
||||
|
||||
/* FIXME: tighten this up, there are some more
|
||||
assertions that hold at task-lifecycle events. */
|
||||
I(sched, ref_count == 0); // ||
|
||||
|
@ -34,7 +34,6 @@ struct gc_alloc {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct
|
||||
rust_task : public kernel_owned<rust_task>, rust_cond
|
||||
{
|
||||
@ -59,6 +58,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond
|
||||
size_t gc_alloc_thresh;
|
||||
size_t gc_alloc_accum;
|
||||
|
||||
rust_task_id id;
|
||||
|
||||
// Keeps track of the last time this task yielded.
|
||||
timer yield_timer;
|
||||
|
||||
|
@ -140,9 +140,11 @@ void upcall_del_chan(rust_task *task, rust_chan *chan) {
|
||||
* has its own copy of the channel.
|
||||
*/
|
||||
extern "C" CDECL rust_chan *
|
||||
upcall_clone_chan(rust_task *task, rust_task *target,
|
||||
upcall_clone_chan(rust_task *task, rust_task_id tid,
|
||||
rust_chan *chan) {
|
||||
// FIXME: This should be removed.
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
rust_task *target = task->kernel->get_task_by_id(tid);
|
||||
return chan->clone(target);
|
||||
}
|
||||
|
||||
@ -203,9 +205,9 @@ upcall_fail(rust_task *task,
|
||||
* Called whenever a task's ref count drops to zero.
|
||||
*/
|
||||
extern "C" CDECL void
|
||||
upcall_kill(rust_task *task, rust_task *target) {
|
||||
upcall_kill(rust_task *task, rust_task_id tid) {
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
|
||||
rust_task *target = task->kernel->get_task_by_id(tid);
|
||||
target->kill();
|
||||
}
|
||||
|
||||
@ -322,9 +324,9 @@ upcall_new_str(rust_task *task, char const *s, size_t fill) {
|
||||
}
|
||||
|
||||
extern "C" CDECL rust_str *
|
||||
upcall_dup_str(rust_task *task, rust_task *target, rust_str *str) {
|
||||
upcall_dup_str(rust_task *task, rust_task_id tid, rust_str *str) {
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
|
||||
rust_task *target = task->kernel->get_task_by_id(tid);
|
||||
return make_str(target, (char const *)str->data, str->fill);
|
||||
}
|
||||
|
||||
@ -482,27 +484,30 @@ upcall_get_type_desc(rust_task *task,
|
||||
return td;
|
||||
}
|
||||
|
||||
extern "C" CDECL rust_task *
|
||||
extern "C" CDECL rust_task_id
|
||||
upcall_new_task(rust_task *spawner, rust_vec *name) {
|
||||
// name is a rust string structure.
|
||||
LOG_UPCALL_ENTRY(spawner);
|
||||
rust_task *task =
|
||||
rust_task_id tid =
|
||||
spawner->kernel->create_task(spawner, (const char *)name->data);
|
||||
rust_task *task = spawner->kernel->get_task_by_id(tid);
|
||||
task->ref();
|
||||
return task;
|
||||
return tid;
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_take_task(rust_task *task, rust_task *target) {
|
||||
upcall_take_task(rust_task *task, rust_task_id tid) {
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
rust_task *target = task->kernel->get_task_by_id(tid);
|
||||
if(target) {
|
||||
target->ref();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_drop_task(rust_task *task, rust_task *target) {
|
||||
upcall_drop_task(rust_task *task, rust_task_id tid) {
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
rust_task *target = task->kernel->get_task_by_id(tid);
|
||||
if(target) {
|
||||
target->deref();
|
||||
}
|
||||
@ -526,13 +531,14 @@ upcall_drop_chan(rust_task *task, rust_chan *target) {
|
||||
|
||||
extern "C" CDECL rust_task *
|
||||
upcall_start_task(rust_task *spawner,
|
||||
rust_task *task,
|
||||
rust_task_id tid,
|
||||
uintptr_t spawnee_fn,
|
||||
uintptr_t args,
|
||||
size_t args_sz) {
|
||||
LOG_UPCALL_ENTRY(spawner);
|
||||
|
||||
rust_scheduler *sched = spawner->sched;
|
||||
rust_task *task = spawner->kernel->get_task_by_id(tid);
|
||||
DLOG(sched, task,
|
||||
"upcall start_task(task %s @0x%" PRIxPTR
|
||||
", spawnee 0x%" PRIxPTR ")",
|
||||
|
@ -45,7 +45,8 @@ void task_entry() {
|
||||
|
||||
void
|
||||
rust_task_test::worker::run() {
|
||||
rust_task *root_task = kernel->create_task(NULL, "main");
|
||||
rust_task_id root_id = kernel->create_task(NULL, "main");
|
||||
rust_task *root_task = kernel->get_task_by_id(root_id);
|
||||
root_task->start((uintptr_t)&task_entry, (uintptr_t)NULL);
|
||||
root_task->sched->start_main_loop();
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- c++ -*-
|
||||
/**
|
||||
* A C++ wrapper around uthash.
|
||||
*/
|
||||
|
@ -4,12 +4,11 @@ import std::comm;
|
||||
|
||||
fn start(pcc: *u8) {
|
||||
let c = comm::chan_from_unsafe_ptr(pcc);
|
||||
let p;
|
||||
let p = comm::mk_port[str]();
|
||||
c.send(p.mk_chan().unsafe_ptr());
|
||||
|
||||
let a;
|
||||
let b;
|
||||
p = comm::mk_port[str]();
|
||||
c.send(p.mk_chan().unsafe_ptr());
|
||||
a = p.recv();
|
||||
log_err a;
|
||||
b = p.recv();
|
||||
@ -17,15 +16,11 @@ fn start(pcc: *u8) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p : comm::_port[*u8];
|
||||
let child;
|
||||
let p = comm::mk_port[*u8]();
|
||||
let child = spawn start(p.mk_chan().unsafe_ptr());
|
||||
|
||||
p = comm::mk_port();
|
||||
child = spawn start(p.mk_chan().unsafe_ptr());
|
||||
let pc; let c;
|
||||
|
||||
pc = p.recv();
|
||||
c = comm::chan_from_unsafe_ptr(pc);
|
||||
let pc = p.recv();
|
||||
let c = comm::chan_from_unsafe_ptr(pc);
|
||||
c.send("A");
|
||||
c.send("B");
|
||||
task::yield();
|
||||
|
Loading…
Reference in New Issue
Block a user