]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/orb.h
Some weak symbol usage, and some marshalling stuff.
[polintos/scott/priv.git] / include / c++ / orb.h
1 #ifndef _CPP_ORB_H
2 #define _CPP_ORB_H
3
4 #include <stdint.h>
5 #include <stddef.h>
6 #include <string.h>
7 #include <limits.h>
8
9 #include <lowlevel/barriers.h>
10 #include <lowlevel/bitops.h>
11
12 namespace System {
13         struct _i_Object;
14
15         namespace Mem {
16                 struct Region;
17         }
18
19         namespace RunTime {
20                 class ORBMM {
21                         void *priv;
22                         
23                 public:
24                         class AllocGroup {
25                                 friend class ORBMM;
26                         };
27                         
28                         typedef ::System::Mem::Region Region;
29                         
30                         ORBMM();
31                         
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);
36                 };
37                 
38                 extern ORBMM *orbmm;
39                 
40                 // FIXME: should be an IDL exception
41                 struct ArrayException
42                 {
43                 };
44                 
45                 class NullArray {
46                 };
47                 
48                 static const NullArray nullarray = {};
49                 
50                 template<typename T> struct MutableArray {
51                         T *ptr;
52                         size_t count;
53                 
54                         bool valid_index(size_t index)
55                         {
56                                 return index >= 0 && index < count;
57                         }
58                         
59                         T &operator[](size_t index)
60                         {
61 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
62                                 if (!valid_index(index))
63                                         throw ArrayException();
64 #endif
65                 
66                                 return ptr[index];
67                         }
68                         
69                         MutableArray()
70                         {
71                                 ptr = NULL;
72                                 count = 0;
73                         }
74                         
75                         MutableArray(NullArray na)
76                         {
77                                 ptr = NULL;
78                                 count = 0;
79                         }
80                         
81                         MutableArray(T *PTR, size_t COUNT)
82                         {
83                                 ptr = PTR;
84                                 count = COUNT;
85                         }
86                         
87                         MutableArray &slice_nocheck(size_t first, size_t newcount)
88                         {
89                                 MutableArray ret;
90                                 ret.ptr = ptr + first;
91                                 ret.count = newcount;
92                                 return ret;
93                         }
94
95                         MutableArray &slice_nocheck(size_t first)
96                         {
97                                 MutableArray ret;
98                                 ret.ptr = ptr + first;
99                                 ret.count = count - first;
100                                 return ret;
101                         }
102
103                         MutableArray &slice(size_t first, size_t count)
104                         {
105 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
106                                 if (!valid_index(first) || !valid_index(first + count - 1))
107                                         throw ArrayException();
108 #endif
109                                 
110                                 return slice_nocheck(first, count);
111                         }
112
113                         MutableArray &slice(size_t first)
114                         {
115 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
116                                 if (!valid_index(first))
117                                         throw ArrayException();
118 #endif
119                                 
120                                 return slice_nocheck(first);
121                         }
122                         
123                         MutableArray copy()
124                         {
125                                 MutableArray new_arr;
126                                 new_arr.ptr = new(orbmm) T[count];
127                                 new_arr.count = count;
128                                 memcpy(new_arr.ptr, ptr, count);
129                                 return new_arr;
130                         }
131                 };
132                 
133                 template<typename T>
134                 struct GrowableArray : public MutableArray<T> {
135                         using MutableArray<T>::ptr;
136                         using MutableArray<T>::count;
137                         size_t bufsize;
138                         
139                         GrowableArray()
140                         {
141                                 bufsize = 0;
142                         }
143                         
144                         GrowableArray(NullArray na) : MutableArray<T>(na)
145                         {
146                                 bufsize = 0;
147                         }
148                         
149                         GrowableArray(T *PTR, size_t COUNT) : MutableArray<T>(PTR, COUNT)
150                         {
151                                 bufsize = COUNT;
152                         }
153                         
154                         GrowableArray(T *PTR, size_t COUNT, size_t BUFSIZE) :
155                         MutableArray<T>(PTR, COUNT)
156                         {
157                                 bufsize = BUFSIZE;
158                         }
159                         
160                         GrowableArray(MutableArray<T> &ma) : MutableArray<T>(ma)
161                         {
162                                 bufsize = count;
163                         }
164                         
165                         void grow(size_t newsize)
166                         {
167                                 if (newsize <= bufsize)
168                                         return;
169                                 
170                                 T *oldptr = ptr;
171                                 T *newptr = new(orbmm) T[newsize];
172                                 memcpy(newptr, ptr, count * sizeof(T));
173                                 ptr = newptr;
174                                 ll_smp_membar_store_after_store();
175                                 bufsize = newsize;
176                                 // FIXME: Should release imply membar?
177                                 ll_smp_membar_any_after_store();
178                                 orbmm->release(oldptr);
179                         }
180                         
181                         // Caller must sync against all writers.
182                         void append(T *newptr, size_t len, size_t max = ULONG_MAX)
183                         {
184                                 if (count + len < count)
185                                         throw ArrayException();
186                                 
187                                 if (count + len > max)
188                                         throw ArrayException();
189                                 
190                                 if (count + len > bufsize)
191                                         grow(ll_get_order_round_up(count + len));
192                                 
193                                 memcpy(ptr + count, newptr, len * sizeof(T));
194                                 count += len;
195                         }
196                 };
197
198                 template<typename T> struct Array {
199                         const T *ptr;
200                         size_t count;
201                 
202                         bool valid_index(size_t index)
203                         {
204                                 return index >= 0 && index < count;
205                         }
206                         
207                         const T &operator[](size_t index)
208                         {
209 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
210                                 if (!valid_index(index))
211                                         throw ArrayException();
212 #endif
213                 
214                                 return ptr[index];
215                         }
216                         
217                         Array()
218                         {
219                                 ptr = NULL;
220                                 count = 0;
221                         }
222                         
223                         Array(NullArray na)
224                         {
225                                 ptr = NULL;
226                                 count = 0;
227                         }
228                         
229                         Array(const T *PTR, size_t COUNT)
230                         {
231                                 ptr = PTR;
232                                 count = COUNT;
233                         }
234                         
235                         Array(MutableArray<T> ma)
236                         {
237                                 ptr = ma.ptr;
238                                 count = ma.count;
239                         }
240                         
241                         MutableArray<T> constcast()
242                         {
243                                 MutableArray<T> ma;
244                                 ma.ptr = const_cast<T>(ptr);
245                                 ma.count = count;
246                                 return ma;
247                         }
248                         
249                         Array &slice_nocheck(size_t first, size_t newcount)
250                         {
251                                 Array ret;
252                                 ret.ptr = ptr + first;
253                                 ret.count = newcount;
254                                 return ret;
255                         }
256
257                         Array &slice_nocheck(size_t first)
258                         {
259                                 Array ret;
260                                 ret.ptr = ptr + first;
261                                 ret.count = count - first;
262                                 return ret;
263                         }
264
265                         Array &slice(size_t first, size_t count)
266                         {
267 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
268                                 if (!valid_index(first) || !valid_index(first + count - 1))
269                                         throw ArrayException();
270 #endif
271                                 
272                                 return slice_nocheck(first, count);
273                         }
274
275                         Array &slice(size_t first)
276                         {
277 #ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
278                                 if (!valid_index(first))
279                                         throw ArrayException();
280 #endif
281                                 
282                                 return slice_nocheck(first);
283                         }
284                         
285                         MutableArray<T> copy()
286                         {
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);
291                                 return new_arr;
292                         }
293                 };
294
295                 static inline Array<uint8_t> countarray(const char *ptr)
296                 {
297                         Array<uint8_t> ret;
298                         ret.ptr = reinterpret_cast<const uint8_t *>(ptr);
299                         ret.count = strlen(ptr);
300                         return ret;
301                 }
302
303                 static inline MutableArray<uint8_t> countarray(char *ptr)
304                 {
305                         MutableArray<uint8_t> ret;
306                         ret.ptr = reinterpret_cast<uint8_t *>(ptr);
307                         ret.count = strlen(ptr);
308                         return ret;
309                 }
310                 
311                 struct IFaceInfo;
312                 typedef uint32_t ID;
313
314                 struct IFaceTable {
315                         const IFaceInfo *info;
316                         const ptrdiff_t offset;
317                 };
318                 
319                 union GUID {
320                         unsigned char c[16];
321                         unsigned long l[];
322                 };
323
324                 uintptr_t downcast(::System::_i_Object *obj, const GUID *new_guid);
325
326                 // FIXME: use above typedef
327                 static inline bool guids_equal(const unsigned long *guid1,
328                                                const unsigned long *guid2)
329                 {
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])));
335                 }
336                 
337                 struct ParamInfoBlock {
338                         uint32_t buffer_size;
339                         uint32_t copy_size;
340                         ID *objlist, *newobj;
341                         uint32_t objlist_len, newobj_len;
342                         uint32_t num_segments;
343
344                         struct Segment {
345                                 uint8_t *ptr;
346                                 uintptr_t len;
347                                 uintptr_t flags;
348                                 uintptr_t reserved;
349                                 
350                                 enum {
351                                         In = 1,
352                                         Out = 2,
353                                         Inline = 4,
354                                         Copy = 8
355                                 };
356                         } segments[0];
357                 };
358                 
359                 struct Segment0 {
360                         enum {
361                                 InvokeMethod = 0,
362                                 GetIFaces = 1,
363                                 ReturnIFaces = 2,
364                         };
365                 
366                         union {
367                                 struct {
368                                         uint8_t opcode;
369                                 };
370                                 
371                                 unsigned long pad;
372                         };
373                 };
374                         
375                 struct InvokeMethod {
376                         Segment0 seg0;
377                         uint32_t iface;
378                         uint32_t method;
379                         uint8_t args[0];
380                 };
381                 
382                 union Message {
383                         Segment0 seg0;
384                         InvokeMethod invoke;
385                 };
386
387                 struct IFaceInfo {
388                         const GUID *guid;
389                         void (*invoke)(Array<ID> objlist,
390                                        ParamInfoBlock::Segment *segs,
391                                        int nsegs);
392                         ::System::_i_Object *(*wrapper)(ID id);
393                 };
394                 
395                 struct NewObject {
396                         uint32_t guid_hash[5]; // SHA-1 hash of Interface GUIDs
397                         uint32_t id;
398                         uint32_t reserved[3]; // must be zero
399                 };
400
401                 struct VStructInfo {
402                         // List of GUIDs of the struct and its superstructs,
403                         // starting with System.VStruct and ending with
404                         // the concrete struct.
405                         
406                         const unsigned long *const *const guids;
407
408                         // Length of inheritance chain; 1 for System.VStruct
409                         
410                         const int chainlen;
411
412                         int (*marshall)(GrowableArray<uint8_t> &buf,
413                                         GrowableArray<ID> &objlist,
414                                         GrowableArray<NewObject> &newobjlist,
415                                         ParamInfoBlock::Segment *segs,
416                                         int nsegs);
417                         void (*unmarshall)(Array<uint8_t> buf,
418                                            Array< ::System::_i_Object *> objlist,
419                                            ParamInfoBlock::Segment *segs,
420                                            int nsegs);
421                 };
422                 
423                 namespace Priv {
424                         // Return the caller's PC.  It'd be nice if GCC had a builtin for
425                         // the current PC, so that a simple relocation could be used rather
426                         // than a function call.  OPT: put this in lowlevel-lib, so that
427                         // architectures can provide a faster version.
428                         
429                         unsigned long get_pc();
430
431                         static inline bool in_kernel()
432                         {
433 #ifdef _KERNEL
434                                 return true;
435 #else
436                                 return false;
437 #endif
438                         }
439                 }
440         };
441 }
442
443 inline void *operator new(size_t len, ::System::RunTime::ORBMM *orbmm,
444                           int refs = 1)
445 {
446         return orbmm->alloc(len, refs);
447 }
448
449 inline void *operator new[](size_t len, ::System::RunTime::ORBMM *orbmm,
450                             int refs = 1)
451 {
452         return orbmm->alloc(len, refs);
453 }
454
455 // FIXME: This isn't safe on anything with a descructor.
456 inline void operator delete(void *ptr, ::System::RunTime::ORBMM *orbmm,
457                             int refs = 1)
458 {
459         orbmm->release(ptr, refs);
460 }
461
462 inline void operator delete[](void *ptr, ::System::RunTime::ORBMM *orbmm,
463                               int refs = 1)
464 {
465         orbmm->release(ptr, refs);
466 }
467
468 // This is a macro rather than an inline template function so that the
469 // caller shows up as file/line number in the debugging information rather
470 // than this header file, and so that a variable argument list can be
471 // passed to a fixed arg ctor.
472 //
473 // To throw an IDL exception of type Foo, do this:
474 // throw_idl(Foo, args, to, foo);
475
476 #ifndef POLINTOS_NO_THROW_IDL
477 #define throw_idl(T, args...) do { \
478         throw T(NULL, NULL, \
479                 new(::System::RunTime::orbmm) \
480                    ::System::Exceptions::NativeCodeExceptionOriginInfo \
481                    (::System::RunTime::Priv::get_pc()), \
482                 ::System::RunTime::Priv::in_kernel(), ##args); \
483 } while (0)
484
485 #define rethrow_idl(oldex, T, args...) do { \
486         throw T(new(::System::RunTime::orbmm) typeof(oldex)(oldex), NULL, \
487                 new(::System::RunTime::orbmm) \
488                    ::System::Exceptions::NativeCodeExceptionOriginInfo \
489                    (::System::RunTime::Priv::get_pc()), \
490                 ::System::RunTime::Priv::in_kernel(), ##args); \
491 } while (0)
492 #endif
493
494 #endif