rust/src/rt/rust_internal.h

324 lines
7.3 KiB
C++

#ifndef RUST_INTERNAL_H
#define RUST_INTERNAL_H
#ifndef GLOBALS_H
// these are defined in two files, and GCC complains.
#define __STDC_LIMIT_MACROS 1
#define __STDC_CONSTANT_MACROS 1
#define __STDC_FORMAT_MACROS 1
#endif
#define ERROR 0
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <math.h>
#include "rust.h"
#include "rand.h"
#include "uthash.h"
#include "rust_env.h"
#if defined(__WIN32__)
extern "C" {
#include <windows.h>
#include <tchar.h>
#include <wincrypt.h>
}
#elif defined(__GNUC__)
#include <unistd.h>
#include <dlfcn.h>
#include <pthread.h>
#include <errno.h>
#include <dirent.h>
#else
#error "Platform not supported."
#endif
#include "util/array_list.h"
#include "util/indexed_list.h"
#include "util/synchronized_indexed_list.h"
#include "util/hash_map.h"
#include "sync/sync.h"
#include "sync/timer.h"
#include "sync/lock_and_signal.h"
#include "sync/lock_free_queue.h"
struct rust_scheduler;
struct rust_task;
class rust_log;
class rust_port;
class rust_chan;
struct rust_token;
class rust_kernel;
class rust_crate_cache;
struct stk_seg;
struct type_desc;
struct frame_glue_fns;
#ifndef __i386__
#error "Target CPU not supported."
#endif
#define I(dom, e) ((e) ? (void)0 : \
(dom)->srv->fatal(#e, __FILE__, __LINE__, ""))
#define W(dom, e, s, ...) ((e) ? (void)0 : \
(dom)->srv->warning(#e, __FILE__, __LINE__, s, ## __VA_ARGS__))
#define A(dom, e, s, ...) ((e) ? (void)0 : \
(dom)->srv->fatal(#e, __FILE__, __LINE__, s, ## __VA_ARGS__))
#define K(srv, e, s, ...) ((e) ? (void)0 : \
srv->fatal(#e, __FILE__, __LINE__, s, ## __VA_ARGS__))
#define PTR "0x%" PRIxPTR
// This drives our preemption scheme.
static size_t const TIME_SLICE_IN_MS = 10;
// Since every refcounted object is > 4 bytes, any refcount with any of the
// top two bits set is invalid. We reserve a particular bit pattern in this
// set for indicating objects that are "constant" as far as the memory model
// knows.
static intptr_t const CONST_REFCOUNT = 0x7badface;
// This accounts for logging buffers.
static size_t const BUF_BYTES = 2048;
// Every reference counted object should derive from this base class.
// Or use this macro. The macro is preferred as the base class will be
// disappearing.
#define RUST_REFCOUNTED(T) \
RUST_REFCOUNTED_WITH_DTOR(T, delete (T*)this)
#define RUST_REFCOUNTED_WITH_DTOR(T, dtor) \
intptr_t ref_count; \
void ref() { ++ref_count; } \
void deref() { if (--ref_count == 0) { dtor; } }
template <typename T> struct rc_base {
RUST_REFCOUNTED(T)
rc_base();
~rc_base();
};
template <typename T> struct task_owned {
inline void *operator new(size_t size, rust_task *task, const char *tag);
inline void *operator new[](size_t size, rust_task *task,
const char *tag);
inline void *operator new(size_t size, rust_task &task, const char *tag);
inline void *operator new[](size_t size, rust_task &task,
const char *tag);
void operator delete(void *ptr) {
((T *)ptr)->task->free(ptr);
}
};
template<class T>
class smart_ptr {
T *p;
smart_ptr(const smart_ptr &sp) : p(sp.p) {
if(p) { p->ref(); }
}
public:
smart_ptr() : p(NULL) {};
smart_ptr(T *p) : p(p) { if(p) { p->ref(); } }
~smart_ptr() {
if(p) {
p->deref();
}
}
T *operator=(T* p) {
if(this->p) {
this->p->deref();
}
if(p) {
p->ref();
}
this->p = p;
return p;
}
T *operator->() const { return p; };
operator T*() const { return p; }
};
template <typename T> struct kernel_owned {
inline void *operator new(size_t size, rust_kernel *kernel,
const char *tag);
void operator delete(void *ptr) {
((T *)ptr)->kernel->free(ptr);
}
};
template <typename T> struct region_owned {
void operator delete(void *ptr) {
((T *)ptr)->region->free(ptr);
}
};
#include "rust_task_list.h"
// A cond(ition) is something we can block on. This can be a channel
// (writing), a port (reading) or a task (waiting).
struct rust_cond { };
// Helper class used regularly elsewhere.
template <typename T> class ptr_vec : public task_owned<ptr_vec<T> > {
static const size_t INIT_SIZE = 8;
rust_task *task;
size_t alloc;
size_t fill;
T **data;
public:
ptr_vec(rust_task *task);
~ptr_vec();
size_t length() {
return fill;
}
bool is_empty() {
return fill == 0;
}
T *& operator[](size_t offset);
void push(T *p);
T *pop();
T *peek();
void trim(size_t fill);
void swap_delete(T* p);
};
#include "memory_region.h"
#include "rust_srv.h"
#include "rust_log.h"
#include "rust_kernel.h"
#include "rust_scheduler.h"
struct rust_timer {
// FIXME: This will probably eventually need replacement
// with something more sophisticated and integrated with
// an IO event-handling library, when we have such a thing.
// For now it's just the most basic "thread that can interrupt
// its associated domain-thread" device, so that we have
// *some* form of task-preemption.
rust_scheduler *sched;
uintptr_t exit_flag;
#if defined(__WIN32__)
HANDLE thread;
#else
pthread_attr_t attr;
pthread_t thread;
#endif
rust_timer(rust_scheduler *sched);
~rust_timer();
};
#include "rust_util.h"
typedef void CDECL (glue_fn)(void *, rust_task *, void *,
const type_desc **, void *);
typedef void CDECL (cmp_glue_fn)(void *, rust_task *, void *,
const type_desc **,
void *, void *, int8_t);
struct rust_shape_tables {
uint8_t *tags;
uint8_t *resources;
};
struct type_desc {
// First part of type_desc is known to compiler.
// first_param = &descs[1] if dynamic, null if static.
const type_desc **first_param;
size_t size;
size_t align;
glue_fn *copy_glue;
glue_fn *drop_glue;
glue_fn *free_glue;
glue_fn *sever_glue; // For GC.
glue_fn *mark_glue; // For GC.
glue_fn *obj_drop_glue; // For custom destructors.
uintptr_t is_stateful;
cmp_glue_fn *cmp_glue;
const uint8_t *shape;
const rust_shape_tables *shape_tables;
uint32_t n_params;
// Residual fields past here are known only to runtime.
UT_hash_handle hh;
size_t n_descs;
const type_desc *descs[];
};
// An alarm can be put into a wait queue and the task will be notified
// when the wait queue is flushed.
struct
rust_alarm
{
rust_task *receiver;
size_t idx;
rust_alarm(rust_task *receiver);
};
typedef ptr_vec<rust_alarm> rust_wait_queue;
#include "circular_buffer.h"
#include "rust_task.h"
#include "rust_chan.h"
#include "rust_port.h"
#include "memory.h"
extern "C" CDECL void
port_recv(rust_task *task, uintptr_t *dptr, rust_port *port);
#include "test/rust_test_harness.h"
#include "test/rust_test_util.h"
#include "test/rust_test_runtime.h"
//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
#endif