qom: Allow objects to be allocated with increased alignment

It turns out that some hosts have a default malloc alignment less
than that required for vectors.

We assume that, with compiler annotation on CPUArchState, that we
can properly align the vector portion of the guest state. Fix the
alignment of the allocation by using qemu_memalloc when required.
This commit is contained in:
Richard Henderson 2021-03-01 18:32:40 -05:00 committed by Lioncash
parent 6baafeafd4
commit 86dd30850d
2 changed files with 37 additions and 3 deletions

View File

@ -439,6 +439,9 @@ struct Object
* @instance_size: The size of the object (derivative of #Object). If
* @instance_size is 0, then the size of the object will be the size of the
* parent object.
* @instance_align: The required alignment of the object. If @instance_align
* is 0, then normal malloc alignment is sufficient; if non-zero, then we
* must use qemu_memalign for allocation.
* @instance_init: This function is called to initialize an object. The parent
* class will have already been initialized so the type is only responsible
* for initializing its own members.
@ -479,6 +482,7 @@ struct TypeInfo
size_t class_size;
size_t instance_size;
size_t instance_align;
void *instance_userdata;
void (*instance_init)(struct uc_struct *uc, Object *obj, void *opaque);

View File

@ -45,6 +45,7 @@ struct TypeImpl
size_t class_size;
size_t instance_size;
size_t instance_align;
void *instance_userdata;
void (*class_init)(struct uc_struct *uc, ObjectClass *klass, void *data);
@ -103,6 +104,7 @@ static TypeImpl *type_new(struct uc_struct *uc, const TypeInfo *info)
ti->class_size = info->class_size;
ti->instance_size = info->instance_size;
ti->instance_align = info->instance_align;
ti->class_init = info->class_init;
ti->class_base_init = info->class_base_init;
@ -479,16 +481,44 @@ static void object_finalize(struct uc_struct *uc, void *data)
}
}
/* Find the minimum alignment guaranteed by the system malloc. */
#if __STDC_VERSION__ >= 201112L
typddef max_align_t qemu_max_align_t;
#else
typedef union {
long l;
void *p;
double d;
long double ld;
} qemu_max_align_t;
#endif
static Object *object_new_with_type(struct uc_struct *uc, Type type)
{
Object *obj;
size_t size, align;
void (*obj_free)(void *);
g_assert(type != NULL);
type_initialize(uc, type);
obj = g_malloc(type->instance_size);
object_initialize_with_type(uc, obj, type->instance_size, type);
obj->free = g_free;
size = type->instance_size;
align = type->instance_align;
/*
* Do not use qemu_memalign unless required. Depending on the
* implementation, extra alignment implies extra overhead.
*/
if (likely(align <= __alignof__(qemu_max_align_t))) {
obj = g_malloc(size);
obj_free = g_free;
} else {
obj = qemu_memalign(align, size);
obj_free = qemu_vfree;
}
object_initialize_with_type(uc, obj, size, type);
obj->free = obj_free;
return obj;
}