Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime work #716

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/comp/back/upcall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type upcalls =
ValueRef flush_chan,
ValueRef del_chan,
ValueRef clone_chan,
ValueRef chan_target_task,
ValueRef _yield,
ValueRef sleep,
ValueRef send,
Expand Down Expand Up @@ -95,6 +96,9 @@ fn declare_upcalls(type_names tn, TypeRef tydesc_type, TypeRef taskptr_type,
del_chan=dv("del_chan", ~[T_opaque_chan_ptr()]),
clone_chan=d("clone_chan", ~[taskptr_type, T_opaque_chan_ptr()],
T_opaque_chan_ptr()),
chan_target_task=d("chan_target_task",
~[T_opaque_chan_ptr()],
taskptr_type),
_yield=dv("yield", empty_vec),
sleep=dv("sleep", ~[T_size_t()]),
send=dv("send", ~[T_opaque_chan_ptr(), T_ptr(T_i8())]),
Expand Down
119 changes: 60 additions & 59 deletions src/comp/middle/trans_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ import back::link::mangle_internal_name_by_path_and_seq;
import trans_common::*;
import trans::*;

export trans_port;
export trans_chan;
export trans_spawn;
export trans_send;
export trans_recv;

fn trans_port(&@block_ctxt cx, ast::node_id id) -> result {
auto t = node_id_type(cx.fcx.lcx.ccx, id);
auto unit_ty;
Expand Down Expand Up @@ -123,13 +129,7 @@ fn trans_spawn(&@block_ctxt cx, &ast::spawn_dom dom, &option::t[str] name,
auto llargs = alloc_ty(bcx, args_ty);
auto i = 0u;
for (ValueRef v in arg_vals) {
// log_err #fmt("ty(llargs) = %s",
// val_str(bcx.fcx.lcx.ccx.tn, llargs.val));

auto target = bcx.build.GEP(llargs.val, ~[C_int(0), C_int(i as int)]);
// log_err #fmt("ty(v) = %s", val_str(bcx.fcx.lcx.ccx.tn, v));
// log_err #fmt("ty(target) = %s",
// val_str(bcx.fcx.lcx.ccx.tn, target));

bcx.build.Store(v, target);
i += 1u;
Expand Down Expand Up @@ -199,55 +199,6 @@ fn mk_spawn_wrapper(&@block_ctxt cx, &@ast::expr func, &ty::t args_ty) ->
ret rslt(cx, llfndecl);
}

// Does a deep copy of a value. This is needed for passing arguments to child
// tasks, and for sending things through channels. There are probably some
// uniqueness optimizations and things we can do here for tasks in the same
// domain.
fn deep_copy(&@block_ctxt bcx, ValueRef v, ty::t t, ValueRef target_task)
-> result
{
// TODO: make sure all paths add any reference counting that they need to.

// TODO: Teach deep copy to understand everything else it needs to.

auto tcx = bcx.fcx.lcx.ccx.tcx;
if(ty::type_is_scalar(tcx, t)) {
ret rslt(bcx, v);
}
else if(ty::type_is_str(tcx, t)) {
ret rslt(bcx,
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.dup_str,
~[bcx.fcx.lltaskptr, target_task, v]));
}
else if(ty::type_is_chan(tcx, t)) {
// If this is a channel, we need to clone it.
auto chan_ptr = bcx.build.PointerCast(v, T_opaque_chan_ptr());

auto chan_raw_val =
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.clone_chan,
~[bcx.fcx.lltaskptr, target_task, chan_ptr]);

// Cast back to the type the context was expecting.
auto chan_val = bcx.build.PointerCast(chan_raw_val,
val_ty(v));

ret rslt(bcx, chan_val);
}
else if(ty::type_is_structural(tcx, t)) {
fn inner_deep_copy(&@block_ctxt bcx, ValueRef v, ty::t t) -> result {
log_err "Unimplemented type for deep_copy.";
fail;
}

ret iter_structural_ty(bcx, v, t, inner_deep_copy);
}
else {
bcx.fcx.lcx.ccx.sess.bug("unexpected type in " +
"trans::deep_copy: " +
ty_to_str(tcx, t));
}
}

fn trans_send(&@block_ctxt cx, &@ast::expr lhs, &@ast::expr rhs,
ast::node_id id) -> result {
auto bcx = cx;
Expand Down Expand Up @@ -296,9 +247,59 @@ fn recv_val(&@block_ctxt cx, ValueRef to, &@ast::expr from, &ty::t unit_ty,
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.recv,
~[bcx.fcx.lltaskptr, lldataptr, llportptr]);
auto data_load = load_if_immediate(bcx, to, unit_ty);
auto cp = copy_val(bcx, action, to, data_load, unit_ty);
bcx = cp.bcx;
// TODO: Any cleanup need to be done here?
ret rslt(bcx, to);
//auto cp = copy_val(bcx, action, to, data_load, unit_ty);
//bcx = cp.bcx;

add_clean_temp(cx, data_load, unit_ty);
ret rslt(bcx, data_load);
}

// Does a deep copy of a value. This is needed for passing arguments to child
// tasks, and for sending things through channels. There are probably some
// uniqueness optimizations and things we can do here for tasks in the same
// domain.
fn deep_copy(&@block_ctxt bcx, ValueRef v, ty::t t, ValueRef target_task)
-> result
{
// TODO: make sure all paths add any reference counting that they need to.

// TODO: Teach deep copy to understand everything else it needs to.

auto tcx = bcx.fcx.lcx.ccx.tcx;
if(ty::type_is_scalar(tcx, t)) {
ret rslt(bcx, v);
}
else if(ty::type_is_str(tcx, t)) {
ret rslt(bcx,
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.dup_str,
~[bcx.fcx.lltaskptr, target_task, v]));
}
else if(ty::type_is_chan(tcx, t)) {
// If this is a channel, we need to clone it.
auto chan_ptr = bcx.build.PointerCast(v, T_opaque_chan_ptr());

auto chan_raw_val =
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.clone_chan,
~[bcx.fcx.lltaskptr, target_task, chan_ptr]);

// Cast back to the type the context was expecting.
auto chan_val = bcx.build.PointerCast(chan_raw_val,
val_ty(v));

ret rslt(bcx, chan_val);
}
else if(ty::type_is_structural(tcx, t)) {
fn inner_deep_copy(&@block_ctxt bcx, ValueRef v, ty::t t) -> result {
log_err "Unimplemented type for deep_copy.";
fail;
}

ret iter_structural_ty(bcx, v, t, inner_deep_copy);
}
else {
bcx.fcx.lcx.ccx.sess.bug("unexpected type in " +
"trans::deep_copy: " +
ty_to_str(tcx, t));
}
}

22 changes: 11 additions & 11 deletions src/rt/circular_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

#include "rust_internal.h"

circular_buffer::circular_buffer(rust_task *task, size_t unit_sz) :
sched(task->sched),
task(task),
circular_buffer::circular_buffer(rust_kernel *kernel, size_t unit_sz) :
sched(kernel->sched),
kernel(kernel),
unit_sz(unit_sz),
_buffer_sz(initial_size()),
_next(0),
_unread(0),
_buffer((uint8_t *)task->malloc(_buffer_sz)) {
_buffer((uint8_t *)kernel->malloc(_buffer_sz, "circular_buffer")) {

A(sched, unit_sz, "Unit size must be larger than zero.");

Expand All @@ -20,16 +20,14 @@ circular_buffer::circular_buffer(rust_task *task, size_t unit_sz) :
_buffer_sz, _unread, this);

A(sched, _buffer, "Failed to allocate buffer.");
task->ref();
}

circular_buffer::~circular_buffer() {
DLOG(sched, mem, "~circular_buffer 0x%" PRIxPTR, this);
I(sched, _buffer);
W(sched, _unread == 0,
"freeing circular_buffer with %d unread bytes", _unread);
task->free(_buffer);
--task->ref_count;
kernel->free(_buffer);
}

size_t
Expand Down Expand Up @@ -144,9 +142,10 @@ circular_buffer::grow() {
size_t new_buffer_sz = _buffer_sz * 2;
I(sched, new_buffer_sz <= MAX_CIRCULAR_BUFFER_SIZE);
DLOG(sched, mem, "circular_buffer is growing to %d bytes", new_buffer_sz);
void *new_buffer = task->malloc(new_buffer_sz);
void *new_buffer = kernel->malloc(new_buffer_sz,
"new circular_buffer (grow)");
transfer(new_buffer);
task->free(_buffer);
kernel->free(_buffer);
_buffer = (uint8_t *)new_buffer;
_next = 0;
_buffer_sz = new_buffer_sz;
Expand All @@ -158,9 +157,10 @@ circular_buffer::shrink() {
I(sched, initial_size() <= new_buffer_sz);
DLOG(sched, mem, "circular_buffer is shrinking to %d bytes",
new_buffer_sz);
void *new_buffer = task->malloc(new_buffer_sz);
void *new_buffer = kernel->malloc(new_buffer_sz,
"new circular_buffer (shrink)");
transfer(new_buffer);
task->free(_buffer);
kernel->free(_buffer);
_buffer = (uint8_t *)new_buffer;
_next = 0;
_buffer_sz = new_buffer_sz;
Expand Down
6 changes: 3 additions & 3 deletions src/rt/circular_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
#define CIRCULAR_BUFFER_H

class
circular_buffer : public task_owned<circular_buffer> {
circular_buffer : public kernel_owned<circular_buffer> {
static const size_t INITIAL_CIRCULAR_BUFFER_SIZE_IN_UNITS = 8;
static const size_t MAX_CIRCULAR_BUFFER_SIZE = 1 << 24;

rust_scheduler *sched;

public:
rust_task *task;
rust_kernel *kernel;
// Size of the data unit in bytes.
const size_t unit_sz;
circular_buffer(rust_task *task, size_t unit_sz);
circular_buffer(rust_kernel *kernel, size_t unit_sz);
~circular_buffer();
void transfer(void *dst);
void enqueue(void *src);
Expand Down
29 changes: 17 additions & 12 deletions src/rt/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,38 @@
#define MEMORY_H

// FIXME: It would be really nice to be able to get rid of this.
inline void *operator new[](size_t size, rust_task *task) {
return task->malloc(size);
inline void *operator new[](size_t size, rust_task *task, const char *tag) {
return task->malloc(size, tag);
}

template <typename T>
inline void *task_owned<T>::operator new(size_t size, rust_task *task) {
return task->malloc(size);
inline void *task_owned<T>::operator new(size_t size, rust_task *task,
const char *tag) {
return task->malloc(size, tag);
}

template <typename T>
inline void *task_owned<T>::operator new[](size_t size, rust_task *task) {
return task->malloc(size);
inline void *task_owned<T>::operator new[](size_t size, rust_task *task,
const char *tag) {
return task->malloc(size, tag);
}

template <typename T>
inline void *task_owned<T>::operator new(size_t size, rust_task &task) {
return task.malloc(size);
inline void *task_owned<T>::operator new(size_t size, rust_task &task,
const char *tag) {
return task.malloc(size, tag);
}

template <typename T>
inline void *task_owned<T>::operator new[](size_t size, rust_task &task) {
return task.malloc(size);
inline void *task_owned<T>::operator new[](size_t size, rust_task &task,
const char *tag) {
return task.malloc(size, tag);
}

template <typename T>
inline void *kernel_owned<T>::operator new(size_t size, rust_kernel *kernel) {
return kernel->malloc(size);
inline void *kernel_owned<T>::operator new(size_t size, rust_kernel *kernel,
const char *tag) {
return kernel->malloc(size, tag);
}


Expand Down