#include <stdint.h>
#include <stddef.h>
#include <string.h>
+#include <limits.h>
+
+#include <lowlevel/barriers.h>
+#include <lowlevel/bitops.h>
namespace System {
struct _i_Object;
return new_arr;
}
};
+
+ template<typename T>
+ struct GrowableArray : public MutableArray<T> {
+ using MutableArray<T>::ptr;
+ using MutableArray<T>::count;
+ size_t bufsize;
+
+ GrowableArray()
+ {
+ bufsize = 0;
+ }
+
+ GrowableArray(NullArray na) : MutableArray<T>(na)
+ {
+ bufsize = 0;
+ }
+
+ GrowableArray(T *PTR, size_t COUNT) : MutableArray<T>(PTR, COUNT)
+ {
+ bufsize = COUNT;
+ }
+
+ GrowableArray(T *PTR, size_t COUNT, size_t BUFSIZE) :
+ MutableArray<T>(PTR, COUNT)
+ {
+ bufsize = BUFSIZE;
+ }
+
+ GrowableArray(MutableArray<T> &ma) : MutableArray<T>(ma)
+ {
+ bufsize = count;
+ }
+
+ void grow(size_t newsize)
+ {
+ if (newsize <= bufsize)
+ return;
+
+ T *oldptr = ptr;
+ T *newptr = new(orbmm) T[newsize];
+ memcpy(newptr, ptr, count * sizeof(T));
+ ptr = newptr;
+ ll_smp_membar_store_after_store();
+ bufsize = newsize;
+ // FIXME: Should release imply membar?
+ ll_smp_membar_any_after_store();
+ orbmm->release(oldptr);
+ }
+
+ // Caller must sync against all writers.
+ void append(T *newptr, size_t len, size_t max = ULONG_MAX)
+ {
+ if (count + len < count)
+ throw ArrayException();
+
+ if (count + len > max)
+ throw ArrayException();
+
+ if (count + len > bufsize)
+ grow(ll_get_order_round_up(count + len));
+
+ memcpy(ptr + count, newptr, len * sizeof(T));
+ count += len;
+ }
+ };
template<typename T> struct Array {
const T *ptr;
return ret;
}
+ struct IFaceInfo;
+
struct IFaceTable {
- const unsigned long *const guid;
+ const IFaceInfo *info;
const ptrdiff_t offset;
};
uintptr_t downcast(::System::_i_Object *obj,
const unsigned long *new_guid);
+ typedef uint64_t GUID[2];
+
+ // FIXME: use above typedef
static inline bool guids_equal(const unsigned long *guid1,
const unsigned long *guid2)
{
guid1[3] == guid2[3])));
}
- // Return the caller's PC. It'd be nice if GCC had a builtin for
- // the current PC, so that a simple relocation could be used rather
- // than a function call. OPT: put this in lowlevel-lib, so that
- // architectures can provide a faster version.
-
- unsigned long get_pc();
-
+ typedef uint32_t ID;
struct ParamInfoBlock {
- uintptr_t buffer_size;
- uintptr_t copy_size;
- uintptr_t *objlist_ptr;
- uintptr_t objlist_len;
- uintptr_t num_segments;
+ uint32_t buffer_size;
+ uint32_t copy_size;
+ ID *objlist;
+ uint32_t objlist_len;
+ uint32_t num_segments;
struct Segment {
- void *ptr;
+ uint8_t *ptr;
uintptr_t len;
uintptr_t flags;
uintptr_t reserved;
+
+ enum {
+ In = 1,
+ Out = 2,
+ Inline = 4,
+ Copy = 8
+ };
} segments[0];
};
- }
-
- namespace Priv {
- static inline bool in_kernel()
- {
+
+ struct Segment0 {
+ enum {
+ InvokeMethod = 0,
+ GetIFaces = 1,
+ ReturnIFaces = 2,
+ };
+
+ union {
+ struct {
+ uint8_t opcode;
+ };
+
+ unsigned long pad;
+ };
+ };
+
+ struct InvokeMethod {
+ Segment0 seg0;
+ uint32_t iface;
+ uint32_t method;
+ uint8_t args[0];
+ };
+
+ union Message {
+ Segment0 seg0;
+ InvokeMethod invoke;
+ };
+
+ struct IFaceInfo {
+ static const uint8_t *guid;
+ int (*marshall)(GrowableArray<uint8_t> &buf,
+ GrowableArray<ID> &objlist,
+ ParamInfoBlock::Segment *segs,
+ int nsegs);
+ void (*unmarshall)(Array<uint8_t> buf,
+ Array<ID> objlist,
+ ParamInfoBlock::Segment *segs,
+ int nsegs);
+ };
+
+ namespace Priv {
+ // Return the caller's PC. It'd be nice if GCC had a builtin for
+ // the current PC, so that a simple relocation could be used rather
+ // than a function call. OPT: put this in lowlevel-lib, so that
+ // architectures can provide a faster version.
+
+ unsigned long get_pc();
+
+ static inline bool in_kernel()
+ {
#ifdef _KERNEL
- return true;
+ return true;
#else
- return false;
+ return false;
#endif
+ }
}
};
}
return orbmm->alloc(len, refs);
}
+// FIXME: This isn't safe on anything with a descructor.
inline void operator delete(void *ptr, ::System::RunTime::ORBMM *orbmm,
int refs = 1)
{
throw T(NULL, NULL, \
new(::System::RunTime::orbmm) \
::System::Exceptions::NativeCodeExceptionOriginInfo \
- (::System::RunTime::get_pc()), \
- ::System::Priv::in_kernel(), ##args); \
+ (::System::RunTime::Priv::get_pc()), \
+ ::System::RunTime::Priv::in_kernel(), ##args); \
} while (0)
#define rethrow_idl(oldex, T, args...) do { \
throw T(new(::System::RunTime::orbmm) typeof(oldex)(oldex), NULL, \
new(::System::RunTime::orbmm) \
::System::Exceptions::NativeCodeExceptionOriginInfo \
- (::System::RunTime::get_pc()), \
- ::System::Priv::in_kernel(), ##args); \
+ (::System::RunTime::Priv::get_pc()), \
+ ::System::RunTime::Priv::in_kernel(), ##args); \
} while (0)
#endif