120 lines
2.6 KiB
C
120 lines
2.6 KiB
C
//---
|
|
// hypervisor:table - world allocator
|
|
//---
|
|
#include <vhex/hypervisor.h>
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
/* internal world table */
|
|
static struct {
|
|
struct vhex_world *table;
|
|
size_t table_slot;
|
|
} hyp = {
|
|
.table = NULL,
|
|
.table_slot = 0
|
|
};
|
|
|
|
/* hypervisor_world_new() : create a new world with its name */
|
|
hyp_world_t hypervisor_world_new(char const * const restrict name, int flags)
|
|
{
|
|
struct vhex_driver *dtable;
|
|
hyp_world_t id;
|
|
|
|
/* try to find free world */
|
|
id = 0xb0cad0;
|
|
if (hyp.table != NULL) {
|
|
for (size_t i = 0; i < hyp.table_slot; ++i) {
|
|
if (HYP_WORLD_STATUS_STATE(hyp.table[i].status)
|
|
== HYP_WORLD_STATUS_STATE_UNUSED) {
|
|
id = i;
|
|
continue;
|
|
}
|
|
if (strcmp(hyp.table[i].name, name) == 0)
|
|
return (hyp_world_already_exists);
|
|
|
|
}
|
|
}
|
|
|
|
/* if no world is found, update the table */
|
|
if (id == 0xb0cad0) {
|
|
id = hyp.table_slot;
|
|
|
|
if (hyp.table_slot == 0)
|
|
hyp.table_slot = 1;
|
|
|
|
hyp.table = reallocarray(
|
|
hyp.table,
|
|
hyp.table_slot * 2,
|
|
sizeof(struct vhex_world)
|
|
);
|
|
for (size_t i = hyp.table_slot; i < hyp.table_slot * 2; ++i) {
|
|
hyp.table[i].status = HYP_WORLD_STATUS_STATE_UNUSED;
|
|
hyp.table[i].driver = NULL;
|
|
hyp.table[i].name = NULL;
|
|
}
|
|
|
|
hyp.table_slot = hyp.table_slot * 2;
|
|
}
|
|
|
|
/* initialize the world */
|
|
hyp.table[id].name = strdup(name);
|
|
hyp.table[id].status = HYP_WORLD_STATUS_SET(
|
|
flags,
|
|
HYP_WORLD_STATUS_STATE_UNINIT
|
|
);
|
|
if (hyp.table[id].driver == NULL) {
|
|
hyp.table[id].driver = malloc(
|
|
vhex_driver_count() * sizeof(*hyp.table[id].driver)
|
|
);
|
|
dtable = vhex_driver_table();
|
|
for (int i = 0; i < vhex_driver_count(); ++i) {
|
|
hyp.table[id].driver[i].context = malloc(
|
|
dtable[i].state_size
|
|
);
|
|
}
|
|
}
|
|
|
|
return (id);
|
|
}
|
|
|
|
|
|
/* hypervisor_world_find() : find a world using its name */
|
|
hyp_world_t hypervisor_world_find(char const * const restrict name)
|
|
{
|
|
if (hyp.table != NULL) {
|
|
for (size_t i = 0; i < hyp.table_slot; ++i) {
|
|
if (strcmp(hyp.table[i].name, name) == 0)
|
|
return (i);
|
|
}
|
|
}
|
|
return (hyp_world_not_found);
|
|
}
|
|
|
|
/* hypervisor_world_get() : get a word using its ID */
|
|
struct vhex_world *hypervisor_world_get(hyp_world_t id)
|
|
{
|
|
if (id < 0 || (size_t)id >= hyp.table_slot)
|
|
return (NULL);
|
|
if (HYP_WORLD_STATUS_STATE(hyp.table[id].status)
|
|
== HYP_WORLD_STATUS_STATE_UNUSED) {
|
|
return (NULL);
|
|
}
|
|
return (&hyp.table[id]);
|
|
}
|
|
|
|
|
|
/* hypervisor_world_delete() : remove world */
|
|
hyp_world_t hypervisor_world_delete(hyp_world_t id)
|
|
{
|
|
if (id < 0 || (size_t)id >= hyp.table_slot)
|
|
return (hyp_world_bad_id);
|
|
|
|
if (HYP_WORLD_STATUS_FLAGS(hyp.table[id].status)
|
|
== HYP_WORLD_STATUS_FLAG_UNDELETABLE) {
|
|
return (hyp_world_undeletable);
|
|
}
|
|
|
|
hyp.table[id].status = HYP_WORLD_STATUS_STATE_UNUSED;
|
|
}
|