//--- // hypervisor:table - world allocator //--- #include #include #include /* 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; }