linux-user: save auxv length
[qemu.git] / qom / object.c
1 /*
2 * QEMU Object Model
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13 #include "qemu/object.h"
14 #include "qemu-common.h"
15
16 #define MAX_INTERFACES 32
17
18 typedef struct InterfaceImpl InterfaceImpl;
19 typedef struct TypeImpl TypeImpl;
20
21 struct InterfaceImpl
22 {
23 const char *parent;
24 void (*interface_initfn)(ObjectClass *class, void *data);
25 TypeImpl *type;
26 };
27
28 struct TypeImpl
29 {
30 const char *name;
31
32 size_t class_size;
33
34 size_t instance_size;
35
36 void (*class_init)(ObjectClass *klass, void *data);
37 void (*class_finalize)(ObjectClass *klass, void *data);
38
39 void *class_data;
40
41 void (*instance_init)(Object *obj);
42 void (*instance_finalize)(Object *obj);
43
44 bool abstract;
45
46 const char *parent;
47 TypeImpl *parent_type;
48
49 ObjectClass *class;
50
51 int num_interfaces;
52 InterfaceImpl interfaces[MAX_INTERFACES];
53 };
54
55 typedef struct Interface
56 {
57 Object parent;
58 Object *obj;
59 } Interface;
60
61 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
62
63 static GHashTable *type_table_get(void)
64 {
65 static GHashTable *type_table;
66
67 if (type_table == NULL) {
68 type_table = g_hash_table_new(g_str_hash, g_str_equal);
69 }
70
71 return type_table;
72 }
73
74 static void type_table_add(TypeImpl *ti)
75 {
76 g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
77 }
78
79 static TypeImpl *type_table_lookup(const char *name)
80 {
81 return g_hash_table_lookup(type_table_get(), name);
82 }
83
84 TypeImpl *type_register(const TypeInfo *info)
85 {
86 TypeImpl *ti = g_malloc0(sizeof(*ti));
87
88 g_assert(info->name != NULL);
89
90 if (type_table_lookup(info->name) != NULL) {
91 fprintf(stderr, "Registering `%s' which already exists\n", info->name);
92 abort();
93 }
94
95 ti->name = g_strdup(info->name);
96 ti->parent = g_strdup(info->parent);
97
98 ti->class_size = info->class_size;
99 ti->instance_size = info->instance_size;
100
101 ti->class_init = info->class_init;
102 ti->class_finalize = info->class_finalize;
103 ti->class_data = info->class_data;
104
105 ti->instance_init = info->instance_init;
106 ti->instance_finalize = info->instance_finalize;
107
108 ti->abstract = info->abstract;
109
110 if (info->interfaces) {
111 int i;
112
113 for (i = 0; info->interfaces[i].type; i++) {
114 ti->interfaces[i].parent = info->interfaces[i].type;
115 ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn;
116 ti->num_interfaces++;
117 }
118 }
119
120 type_table_add(ti);
121
122 return ti;
123 }
124
125 TypeImpl *type_register_static(const TypeInfo *info)
126 {
127 return type_register(info);
128 }
129
130 static TypeImpl *type_get_by_name(const char *name)
131 {
132 if (name == NULL) {
133 return NULL;
134 }
135
136 return type_table_lookup(name);
137 }
138
139 static TypeImpl *type_get_parent(TypeImpl *type)
140 {
141 if (!type->parent_type && type->parent) {
142 type->parent_type = type_get_by_name(type->parent);
143 g_assert(type->parent_type != NULL);
144 }
145
146 return type->parent_type;
147 }
148
149 static bool type_has_parent(TypeImpl *type)
150 {
151 return (type->parent != NULL);
152 }
153
154 static size_t type_class_get_size(TypeImpl *ti)
155 {
156 if (ti->class_size) {
157 return ti->class_size;
158 }
159
160 if (type_has_parent(ti)) {
161 return type_class_get_size(type_get_parent(ti));
162 }
163
164 return sizeof(ObjectClass);
165 }
166
167 static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
168 {
169 TypeInfo info = {
170 .instance_size = sizeof(Interface),
171 .parent = iface->parent,
172 .class_size = sizeof(InterfaceClass),
173 .class_init = iface->interface_initfn,
174 .abstract = true,
175 };
176 char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
177
178 info.name = name;
179 iface->type = type_register(&info);
180 g_free(name);
181 }
182
183 static void type_class_init(TypeImpl *ti)
184 {
185 size_t class_size = sizeof(ObjectClass);
186 int i;
187
188 if (ti->class) {
189 return;
190 }
191
192 ti->class_size = type_class_get_size(ti);
193
194 ti->class = g_malloc0(ti->class_size);
195 ti->class->type = ti;
196
197 if (type_has_parent(ti)) {
198 TypeImpl *parent = type_get_parent(ti);
199
200 type_class_init(parent);
201
202 class_size = parent->class_size;
203 g_assert(parent->class_size <= ti->class_size);
204
205 memcpy((void *)ti->class + sizeof(ObjectClass),
206 (void *)parent->class + sizeof(ObjectClass),
207 parent->class_size - sizeof(ObjectClass));
208 }
209
210 memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
211
212 for (i = 0; i < ti->num_interfaces; i++) {
213 type_class_interface_init(ti, &ti->interfaces[i]);
214 }
215
216 if (ti->class_init) {
217 ti->class_init(ti->class, ti->class_data);
218 }
219 }
220
221 static void object_interface_init(Object *obj, InterfaceImpl *iface)
222 {
223 TypeImpl *ti = iface->type;
224 Interface *iface_obj;
225
226 iface_obj = INTERFACE(object_new(ti->name));
227 iface_obj->obj = obj;
228
229 obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
230 }
231
232 static void object_init_with_type(Object *obj, TypeImpl *ti)
233 {
234 int i;
235
236 if (type_has_parent(ti)) {
237 object_init_with_type(obj, type_get_parent(ti));
238 }
239
240 for (i = 0; i < ti->num_interfaces; i++) {
241 object_interface_init(obj, &ti->interfaces[i]);
242 }
243
244 if (ti->instance_init) {
245 ti->instance_init(obj);
246 }
247 }
248
249 void object_initialize_with_type(void *data, TypeImpl *type)
250 {
251 Object *obj = data;
252
253 g_assert(type != NULL);
254 g_assert(type->instance_size >= sizeof(ObjectClass));
255
256 type_class_init(type);
257 g_assert(type->abstract == false);
258
259 memset(obj, 0, type->instance_size);
260 obj->class = type->class;
261 object_init_with_type(obj, type);
262 }
263
264 void object_initialize(void *data, const char *typename)
265 {
266 TypeImpl *type = type_get_by_name(typename);
267
268 object_initialize_with_type(data, type);
269 }
270
271 static void object_deinit(Object *obj, TypeImpl *type)
272 {
273 if (type->instance_finalize) {
274 type->instance_finalize(obj);
275 }
276
277 while (obj->interfaces) {
278 Interface *iface_obj = obj->interfaces->data;
279 obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
280 object_delete(OBJECT(iface_obj));
281 }
282
283 if (type_has_parent(type)) {
284 object_deinit(obj, type_get_parent(type));
285 }
286 }
287
288 void object_finalize(void *data)
289 {
290 Object *obj = data;
291 TypeImpl *ti = obj->class->type;
292
293 object_deinit(obj, ti);
294 }
295
296 Object *object_new_with_type(Type type)
297 {
298 Object *obj;
299
300 g_assert(type != NULL);
301
302 obj = g_malloc(type->instance_size);
303 object_initialize_with_type(obj, type);
304
305 return obj;
306 }
307
308 Object *object_new(const char *typename)
309 {
310 TypeImpl *ti = type_get_by_name(typename);
311
312 return object_new_with_type(ti);
313 }
314
315 void object_delete(Object *obj)
316 {
317 object_finalize(obj);
318 g_free(obj);
319 }
320
321 static bool object_is_type(Object *obj, const char *typename)
322 {
323 TypeImpl *target_type = type_get_by_name(typename);
324 TypeImpl *type = obj->class->type;
325 GSList *i;
326
327 /* Check if typename is a direct ancestor of type */
328 while (type) {
329 if (type == target_type) {
330 return true;
331 }
332
333 type = type_get_parent(type);
334 }
335
336 /* Check if obj has an interface of typename */
337 for (i = obj->interfaces; i; i = i->next) {
338 Interface *iface = i->data;
339
340 if (object_is_type(OBJECT(iface), typename)) {
341 return true;
342 }
343 }
344
345 return false;
346 }
347
348 Object *object_dynamic_cast(Object *obj, const char *typename)
349 {
350 GSList *i;
351
352 /* Check if typename is a direct ancestor */
353 if (object_is_type(obj, typename)) {
354 return obj;
355 }
356
357 /* Check if obj has an interface of typename */
358 for (i = obj->interfaces; i; i = i->next) {
359 Interface *iface = i->data;
360
361 if (object_is_type(OBJECT(iface), typename)) {
362 return OBJECT(iface);
363 }
364 }
365
366 /* Check if obj is an interface and its containing object is a direct
367 * ancestor of typename */
368 if (object_is_type(obj, TYPE_INTERFACE)) {
369 Interface *iface = INTERFACE(obj);
370
371 if (object_is_type(iface->obj, typename)) {
372 return iface->obj;
373 }
374 }
375
376 return NULL;
377 }
378
379
380 static void register_interface(void)
381 {
382 static TypeInfo interface_info = {
383 .name = TYPE_INTERFACE,
384 .instance_size = sizeof(Interface),
385 .abstract = true,
386 };
387
388 type_register_static(&interface_info);
389 }
390
391 device_init(register_interface);
392
393 Object *object_dynamic_cast_assert(Object *obj, const char *typename)
394 {
395 Object *inst;
396
397 inst = object_dynamic_cast(obj, typename);
398
399 if (!inst) {
400 fprintf(stderr, "Object %p is not an instance of type %s\n",
401 obj, typename);
402 abort();
403 }
404
405 return inst;
406 }
407
408 ObjectClass *object_class_dynamic_cast(ObjectClass *class,
409 const char *typename)
410 {
411 TypeImpl *target_type = type_get_by_name(typename);
412 TypeImpl *type = class->type;
413
414 while (type) {
415 if (type == target_type) {
416 return class;
417 }
418
419 type = type_get_parent(type);
420 }
421
422 return NULL;
423 }
424
425 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
426 const char *typename)
427 {
428 ObjectClass *ret = object_class_dynamic_cast(class, typename);
429
430 if (!ret) {
431 fprintf(stderr, "Object %p is not an instance of type %s\n",
432 class, typename);
433 abort();
434 }
435
436 return ret;
437 }
438
439 const char *object_get_typename(Object *obj)
440 {
441 return obj->class->type->name;
442 }
443
444 ObjectClass *object_get_class(Object *obj)
445 {
446 return obj->class;
447 }
448
449 const char *object_class_get_name(ObjectClass *klass)
450 {
451 return klass->type->name;
452 }
453
454 ObjectClass *object_class_by_name(const char *typename)
455 {
456 TypeImpl *type = type_get_by_name(typename);
457
458 if (!type) {
459 return NULL;
460 }
461
462 type_class_init(type);
463
464 return type->class;
465 }
466
467 typedef struct OCFData
468 {
469 void (*fn)(ObjectClass *klass, void *opaque);
470 void *opaque;
471 } OCFData;
472
473 static void object_class_foreach_tramp(gpointer key, gpointer value,
474 gpointer opaque)
475 {
476 OCFData *data = opaque;
477 TypeImpl *type = value;
478
479 type_class_init(type);
480
481 data->fn(value, type->class);
482 }
483
484 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
485 void *opaque)
486 {
487 OCFData data = { fn, opaque };
488
489 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
490 }