9 #include <lowlevel/barriers.h>
10 #include <lowlevel/bitops.h>
28 typedef ::System::Mem::Region Region;
32 void *alloc(size_t size, int refs = 1);
33 void retain(void *ptr, int refs = 1);
34 void release(void *ptr, int refs = 1);
35 void add_region(Region region, bool unmap_orig, int refs = 1);
40 // FIXME: should be an IDL exception
48 static const NullArray nullarray = {};
50 template<typename T> struct MutableArray {
54 bool valid_index(size_t index)
56 return index >= 0 && index < count;
59 T &operator[](size_t index)
61 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
62 if (!valid_index(index))
63 throw ArrayException();
75 MutableArray(NullArray na)
81 MutableArray(T *PTR, size_t COUNT)
87 MutableArray &slice_nocheck(size_t first, size_t newcount)
90 ret.ptr = ptr + first;
95 MutableArray &slice_nocheck(size_t first)
98 ret.ptr = ptr + first;
99 ret.count = count - first;
103 MutableArray &slice(size_t first, size_t count)
105 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
106 if (!valid_index(first) || !valid_index(first + count - 1))
107 throw ArrayException();
110 return slice_nocheck(first, count);
113 MutableArray &slice(size_t first)
115 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
116 if (!valid_index(first))
117 throw ArrayException();
120 return slice_nocheck(first);
125 MutableArray new_arr;
126 new_arr.ptr = new(orbmm) T[count];
127 new_arr.count = count;
128 memcpy(new_arr.ptr, ptr, count);
134 struct GrowableArray : public MutableArray<T> {
135 using MutableArray<T>::ptr;
136 using MutableArray<T>::count;
144 GrowableArray(NullArray na) : MutableArray<T>(na)
149 GrowableArray(T *PTR, size_t COUNT) : MutableArray<T>(PTR, COUNT)
154 GrowableArray(T *PTR, size_t COUNT, size_t BUFSIZE) :
155 MutableArray<T>(PTR, COUNT)
160 GrowableArray(MutableArray<T> &ma) : MutableArray<T>(ma)
165 void grow(size_t newsize)
167 if (newsize <= bufsize)
171 T *newptr = new(orbmm) T[newsize];
172 memcpy(newptr, ptr, count * sizeof(T));
174 ll_smp_membar_store_after_store();
176 // FIXME: Should release imply membar?
177 ll_smp_membar_any_after_store();
178 orbmm->release(oldptr);
181 // Caller must sync against all writers.
182 void append(T *newptr, size_t len, size_t max = ULONG_MAX)
184 if (count + len < count)
185 throw ArrayException();
187 if (count + len > max)
188 throw ArrayException();
190 if (count + len > bufsize)
191 grow(ll_get_order_round_up(count + len));
193 memcpy(ptr + count, newptr, len * sizeof(T));
198 template<typename T> struct Array {
202 bool valid_index(size_t index)
204 return index >= 0 && index < count;
207 const T &operator[](size_t index)
209 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
210 if (!valid_index(index))
211 throw ArrayException();
229 Array(const T *PTR, size_t COUNT)
235 Array(MutableArray<T> ma)
241 MutableArray<T> constcast()
244 ma.ptr = const_cast<T>(ptr);
249 Array &slice_nocheck(size_t first, size_t newcount)
252 ret.ptr = ptr + first;
253 ret.count = newcount;
257 Array &slice_nocheck(size_t first)
260 ret.ptr = ptr + first;
261 ret.count = count - first;
265 Array &slice(size_t first, size_t count)
267 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
268 if (!valid_index(first) || !valid_index(first + count - 1))
269 throw ArrayException();
272 return slice_nocheck(first, count);
275 Array &slice(size_t first)
277 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
278 if (!valid_index(first))
279 throw ArrayException();
282 return slice_nocheck(first);
285 MutableArray<T> copy()
287 MutableArray<T> new_arr;
288 new_arr.ptr = new(orbmm) T[count];
289 new_arr.count = count;
290 memcpy(new_arr.ptr, ptr, count);
295 static inline Array<uint8_t> countarray(const char *ptr)
298 ret.ptr = reinterpret_cast<const uint8_t *>(ptr);
299 ret.count = strlen(ptr);
303 static inline MutableArray<uint8_t> countarray(char *ptr)
305 MutableArray<uint8_t> ret;
306 ret.ptr = reinterpret_cast<uint8_t *>(ptr);
307 ret.count = strlen(ptr);
315 const IFaceInfo *info;
316 const ptrdiff_t offset;
324 uintptr_t downcast(::System::_i_Object *obj, const GUID *new_guid);
326 // FIXME: use above typedef
327 static inline bool guids_equal(const unsigned long *guid1,
328 const unsigned long *guid2)
330 return (guid1[0] == guid2[0] &&
331 guid1[1] == guid2[1] &&
332 (sizeof(long) == 8 ||
333 (guid1[2] == guid2[2] &&
334 guid1[3] == guid2[3])));
337 struct ParamInfoBlock {
338 uint32_t buffer_size;
341 uint32_t objlist_len;
342 uint32_t num_segments;
375 struct InvokeMethod {
389 void (*invoke)(Array<ID> objlist,
390 ParamInfoBlock::Segment *segs,
392 ::System::_i_Object *(*wrapper)(ID id);
396 // List of GUIDs of the struct and its superstructs,
397 // starting with System.VStruct and ending with
398 // the concrete struct.
400 const unsigned long *const *const guids;
402 // Length of inheritance chain; 1 for System.VStruct
406 int (*marshall)(GrowableArray<uint8_t> &buf,
407 GrowableArray<ID> &objlist,
408 ParamInfoBlock::Segment *segs,
410 void (*unmarshall)(Array<uint8_t> buf,
412 ParamInfoBlock::Segment *segs,
417 // Return the caller's PC. It'd be nice if GCC had a builtin for
418 // the current PC, so that a simple relocation could be used rather
419 // than a function call. OPT: put this in lowlevel-lib, so that
420 // architectures can provide a faster version.
422 unsigned long get_pc();
424 static inline bool in_kernel()
436 inline void *operator new(size_t len, ::System::RunTime::ORBMM *orbmm,
439 return orbmm->alloc(len, refs);
442 inline void *operator new[](size_t len, ::System::RunTime::ORBMM *orbmm,
445 return orbmm->alloc(len, refs);
448 // FIXME: This isn't safe on anything with a descructor.
449 inline void operator delete(void *ptr, ::System::RunTime::ORBMM *orbmm,
452 orbmm->release(ptr, refs);
455 inline void operator delete[](void *ptr, ::System::RunTime::ORBMM *orbmm,
458 orbmm->release(ptr, refs);
461 // This is a macro rather than an inline template function so that the
462 // caller shows up as file/line number in the debugging information rather
463 // than this header file, and so that a variable argument list can be
464 // passed to a fixed arg ctor.
466 // To throw an IDL exception of type Foo, do this:
467 // throw_idl(Foo, args, to, foo);
469 #ifndef POLINTOS_NO_THROW_IDL
470 #define throw_idl(T, args...) do { \
471 throw T(NULL, NULL, \
472 new(::System::RunTime::orbmm) \
473 ::System::Exceptions::NativeCodeExceptionOriginInfo \
474 (::System::RunTime::Priv::get_pc()), \
475 ::System::RunTime::Priv::in_kernel(), ##args); \
478 #define rethrow_idl(oldex, T, args...) do { \
479 throw T(new(::System::RunTime::orbmm) typeof(oldex)(oldex), NULL, \
480 new(::System::RunTime::orbmm) \
481 ::System::Exceptions::NativeCodeExceptionOriginInfo \
482 (::System::RunTime::Priv::get_pc()), \
483 ::System::RunTime::Priv::in_kernel(), ##args); \