xref: /openbmc/qemu/qom/object.c (revision 1529ae1bc61a15e9a243dcbad70c95dfcdd1f0c5)
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 }
491