From: Cezar Craciunoiu Date: Thu, 8 Jun 2023 03:55:15 +0000 (+0200) Subject: lib/ukstore: Introduce dynamic API X-Git-Tag: RELEASE-0.14.0~3 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=c3c660851fb6f91ddc65e396ab6dec17b1fe6f32;p=unikraft%2Funikraft.git lib/ukstore: Introduce dynamic API This commit adds dynamic entry support to uk_store. Libraries can dynamically register uk_store objects at runtime, each one of which is associated with one or more entries. Similarly to static entries, each dynamic entry is associated with a getter and / or a setter. Consumers are notified for the lifetime of objects via events. Checkpatch-Ignore: SPACING LONG_LINE GitHub-Closes: #539 Co-authored-by: Michalis Pappas Signed-off-by: Cezar Craciunoiu Signed-off-by: Michalis Pappas Reviewed-by: Simon Kuenzer Reviewed-by: Cezar Craciunoiu Approved-by: Simon Kuenzer Tested-by: Unikraft CI GitHub-Closes: #939 --- diff --git a/lib/ukstore/Config.uk b/lib/ukstore/Config.uk index d3560b5c9..37deabc32 100644 --- a/lib/ukstore/Config.uk +++ b/lib/ukstore/Config.uk @@ -3,4 +3,5 @@ config LIBUKSTORE select LIBNOLIBC if !HAVE_LIBC select LIBUKDEBUG select LIBUKLIBID + select LIBUKLOCK default n diff --git a/lib/ukstore/exportsyms.uk b/lib/ukstore/exportsyms.uk index 783569e25..e17d8d3d4 100644 --- a/lib/ukstore/exportsyms.uk +++ b/lib/ukstore/exportsyms.uk @@ -8,6 +8,16 @@ _uk_store_set_u64 _uk_store_set_s64 _uk_store_set_uptr _uk_store_set_charp +_uk_store_create_dynamic_entry_u8 +_uk_store_create_dynamic_entry_s8 +_uk_store_create_dynamic_entry_u16 +_uk_store_create_dynamic_entry_s16 +_uk_store_create_dynamic_entry_u32 +_uk_store_create_dynamic_entry_s32 +_uk_store_create_dynamic_entry_u64 +_uk_store_create_dynamic_entry_s64 +_uk_store_create_dynamic_entry_uptr +_uk_store_create_dynamic_entry_charp _uk_store_get_u8 _uk_store_get_s8 _uk_store_get_u16 @@ -18,6 +28,12 @@ _uk_store_get_u64 _uk_store_get_s64 _uk_store_get_uptr _uk_store_get_charp -uk_store_get_ncharp -_uk_store_get_static_entry -_uk_store_release_entry +_uk_store_get_ncharp +uk_store_obj_alloc +_uk_store_obj_add +uk_store_obj_acquire +uk_store_obj_release +uk_store_obj_entry_get +uk_store_static_entry_get +uk_event_UKSTORE_EVENT_CREATE_OBJECT +uk_event_UKSTORE_EVENT_RELEASE_OBJECT diff --git a/lib/ukstore/include/uk/store.h b/lib/ukstore/include/uk/store.h index 7b04794ad..2067a40b9 100644 --- a/lib/ukstore/include/uk/store.h +++ b/lib/ukstore/include/uk/store.h @@ -29,24 +29,24 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #ifndef __UK_STORE_H__ #define __UK_STORE_H__ #if CONFIG_LIBUKSTORE #include +#include #include #include -#include #include -#include #include #endif /* CONFIG_LIBUKSTORE */ +#include #include #include +#include #ifdef __cplusplus extern "C" { @@ -151,8 +151,8 @@ struct uk_store_entry { .id = eid, \ .name = STRINGIFY(entry), \ .type = (UK_STORE_ENTRY_TYPE(e_type)), \ - .get.e_type = (e_get), \ - .set.e_type = (e_set), \ + .get.e_type = (e_get), \ + .set.e_type = (e_set), \ .flags = UK_STORE_ENTRY_FLAG_STATIC \ } @@ -173,20 +173,44 @@ struct uk_store_entry { _UK_STORE_STATIC_ENTRY(id, entry, STRINGIFY(__LIBNAME__), \ e_type, e_get, e_set) -#else /* !CONFIG_LIBUKSTORE */ +#else /* CONFIG_LIBUKSTORE */ /* Library-specific information generated at compile-time */ #include +struct uk_store_object { + /* List for the dynamic objects only */ + struct uk_list_head object_head; + + /* List for the entries in the object */ + struct uk_list_head entry_head; + + /* Allocator to be used in allocations */ + struct uk_alloc *a; + + /* Parent library id */ + __u16 libid; + + /* Object unique id */ + __u64 id; + + /* The object name */ + char *name; + + /* The object's refcount */ + __atomic refcount; + + /* User data */ + void *cookie; +} __align8; + /** - * Checks if an entry is static - * - * @param entry the entry to check - * @return the condition result + * Payload to pass to uk_store events. */ -#define UK_STORE_ENTRY_ISSTATIC(entry) \ - ((entry)->flags & UK_STORE_ENTRY_FLAG_STATIC) - +struct uk_store_event_data { + __u16 library_id; + __u64 object_id; +}; /* Do not call directly */ #define __UK_STORE_STATIC_ENTRY(eid, entry, lib_str, e_type, e_get, e_set)\ static const struct uk_store_entry \ @@ -195,8 +219,8 @@ struct uk_store_entry { .id = eid, \ .name = STRINGIFY(entry), \ .type = (UK_STORE_ENTRY_TYPE(e_type)), \ - .get.e_type = (e_get), \ - .set.e_type = (e_set), \ + .get.e_type = (e_get), \ + .set.e_type = (e_set), \ .flags = UK_STORE_ENTRY_FLAG_STATIC \ } @@ -204,6 +228,27 @@ struct uk_store_entry { #define _UK_STORE_STATIC_ENTRY(id, entry, lib_str, e_type, e_get, e_set)\ __UK_STORE_STATIC_ENTRY(id, entry, lib_str, e_type, e_get, e_set) + +/** + * Helper to create entry array elements for uk_store_create_object() + * + * @_id entry id + * @_name entry name (without quotes) + * @_type entry type, e.g s8, u16, charp + * @get getter function + * @set setter function + */ +#define UK_STORE_ENTRY(_id, _name, _type, _get, _set) \ +( \ + &(struct uk_store_entry) { \ + .id = _id, \ + .name = STRINGIFY(_name), \ + .type = UK_STORE_ENTRY_TYPE(_type), \ + .get._type = _get, \ + .set._type = _set, \ + } \ +) + /** * Adds an entry to the entry section of a library. * @@ -217,57 +262,83 @@ struct uk_store_entry { _UK_STORE_STATIC_ENTRY(id, entry, STRINGIFY(__LIBNAME__), \ e_type, e_get, e_set) -const struct uk_store_entry * -_uk_store_get_static_entry(__u16 library_id, __u64 entry_id); - /** - * Searches for an entry in an object in a library. Increases the refcount. + * Creates an object + * + * Allocates memory and initializes a new uk_store object. * - * @param library_id the id of the library to search in - * @param object_id the id of the object to search (NULL for static entries) - * @param entry_id the id of the entry to search for - * @return the found entry or NULL + * @param a allocator instance to allocate this object from + * @param id the id of the new object + * @param name the name of the new object + * @param entries NULL terminated array of struct uk_store_entry describing + * the entries of this object. These can be defined with the + * UK_STORE_ENTRY helper. You should define the superset of + * entries, including ones disabled by default. At runtime, + * disabled entries are indicated by the return code of + * get_value() + * @param cookie caller defined data. This is passed to the getter function + * @return pointer to the allocated object, errptr otherwise */ -static inline const struct uk_store_entry * -uk_store_get_entry(__u16 library_id, __u64 object_id __unused, - __u64 entry_id) -{ - return _uk_store_get_static_entry(library_id, entry_id); -} +struct uk_store_object * +uk_store_obj_alloc(struct uk_alloc *a, __u64 id, const char *name, + const struct uk_store_entry *entries[], void *cookie); /** - * Decreases the refcount. When it reaches 0, the memory is freed + * Associates an object to the caller library * * Guard this with `#if CONFIG_LIBUKSTORE` * - * @param entry the entry to release + * @param object the object to add to the caller library + * @return 0 on success and < 0 on failure */ -#define uk_store_release_entry(entry) \ - _uk_store_release_entry((entry)) - -void -_uk_store_release_entry(const struct uk_store_entry *entry); +#define uk_store_obj_add(obj) \ + _uk_store_obj_add(uk_libid_self(), (obj)) int -_uk_store_get_u8(const struct uk_store_entry *e, __u8 *out); -int -_uk_store_get_s8(const struct uk_store_entry *e, __s8 *out); -int -_uk_store_get_u16(const struct uk_store_entry *e, __u16 *out); -int -_uk_store_get_s16(const struct uk_store_entry *e, __s16 *out); -int -_uk_store_get_u32(const struct uk_store_entry *e, __u32 *out); -int -_uk_store_get_s32(const struct uk_store_entry *e, __s32 *out); -int -_uk_store_get_u64(const struct uk_store_entry *e, __u64 *out); -int -_uk_store_get_s64(const struct uk_store_entry *e, __s64 *out); -int -_uk_store_get_uptr(const struct uk_store_entry *e, __uptr *out); -int -_uk_store_get_charp(const struct uk_store_entry *e, char **out); +_uk_store_obj_add(__u16 library_id, struct uk_store_object *object); + +/** + * Acquires an object + * + * Increments the object's refcount and returns the object. + * Evern call must be paired with a call to uk_store_release_object() + * to decrement the refcount. + * + * @param library_id owner library id as returned by uklibid + * @param object_id object id + * @return pointer to object + */ +struct uk_store_object * +uk_store_obj_acquire(__u16 library_id, __u64 object_id); + +/** + * Releases an object + * + * Decrements the object's refcount. + * + * @param object object to release + */ +void uk_store_obj_release(struct uk_store_object *object); + +/** + * Looks up a static entry of a library. + * + * @param libid owner library + * @param entry_id the id of the entry to look up + * @return the matched entry or NULL + */ +const struct uk_store_entry * +uk_store_static_entry_get(__u16 library_id, __u64 entry_id); + +/** + * Looks up an entry in an object of a library. + * + * @param object target object + * @param entry_id the id of the entry to look up + * @return the matched entry or NULL + */ +const struct uk_store_entry * +uk_store_obj_entry_get(struct uk_store_object *object_id, __u64 entry_id); /** * Calls the getter to get it's value. @@ -281,39 +352,17 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out); #define uk_store_get_value(entry, outtype, out) \ _uk_store_get_ ## outtype((entry), (out)) -/** - * Calls the ncharp getter to get it's value. - * The caller must provide a buffer with enough space to store the result. - * The max length of the result is given by maxlen. - * - * @param e the entry to call the getter from - * @param out space to store the result of the call - * @param maxlen the maximum length of the result - * @return 0 or error on fail - */ -int -uk_store_get_ncharp(const struct uk_store_entry *e, char *out, __sz maxlen); - -int -_uk_store_set_u8(const struct uk_store_entry *e, __u8 val); -int -_uk_store_set_s8(const struct uk_store_entry *e, __s8 val); -int -_uk_store_set_u16(const struct uk_store_entry *e, __u16 val); -int -_uk_store_set_s16(const struct uk_store_entry *e, __s16 val); -int -_uk_store_set_u32(const struct uk_store_entry *e, __u32 val); -int -_uk_store_set_s32(const struct uk_store_entry *e, __s32 val); -int -_uk_store_set_u64(const struct uk_store_entry *e, __u64 val); -int -_uk_store_set_s64(const struct uk_store_entry *e, __s64 val); -int -_uk_store_set_uptr(const struct uk_store_entry *e, __uptr val); -int -_uk_store_set_charp(const struct uk_store_entry *e, const char *val); +int _uk_store_get_u8(const struct uk_store_entry *e, __u8 *out); +int _uk_store_get_s8(const struct uk_store_entry *e, __s8 *out); +int _uk_store_get_u16(const struct uk_store_entry *e, __u16 *out); +int _uk_store_get_s16(const struct uk_store_entry *e, __s16 *out); +int _uk_store_get_u32(const struct uk_store_entry *e, __u32 *out); +int _uk_store_get_s32(const struct uk_store_entry *e, __s32 *out); +int _uk_store_get_u64(const struct uk_store_entry *e, __u64 *out); +int _uk_store_get_s64(const struct uk_store_entry *e, __s64 *out); +int _uk_store_get_uptr(const struct uk_store_entry *e, __uptr *out); +int _uk_store_get_charp(const struct uk_store_entry *e, char **out); +int _uk_store_get_ncharp(const struct uk_store_entry *e, char *out, __sz maxlen); /** * Calls the setter to set a new value. @@ -327,6 +376,17 @@ _uk_store_set_charp(const struct uk_store_entry *e, const char *val); #define uk_store_set_value(entry, intype, in) \ _uk_store_set_ ## intype((entry), (in)) +int _uk_store_set_u8(const struct uk_store_entry *e, __u8 val); +int _uk_store_set_s8(const struct uk_store_entry *e, __s8 val); +int _uk_store_set_u16(const struct uk_store_entry *e, __u16 val); +int _uk_store_set_s16(const struct uk_store_entry *e, __s16 val); +int _uk_store_set_u32(const struct uk_store_entry *e, __u32 val); +int _uk_store_set_s32(const struct uk_store_entry *e, __s32 val); +int _uk_store_set_u64(const struct uk_store_entry *e, __u64 val); +int _uk_store_set_s64(const struct uk_store_entry *e, __s64 val); +int _uk_store_set_uptr(const struct uk_store_entry *e, __uptr val); +int _uk_store_set_charp(const struct uk_store_entry *e, const char *val); + #endif /* CONFIG_LIBUKSTORE */ #ifdef __cplusplus diff --git a/lib/ukstore/store.c b/lib/ukstore/store.c index ea47f9047..9de9a1b34 100644 --- a/lib/ukstore/store.c +++ b/lib/ukstore/store.c @@ -29,12 +29,15 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #include #include #include #include #include +#include +#include +#include +#include #include #define _U8_STRLEN (3 + 1) /* 3 digits plus terminating '\0' */ @@ -47,24 +50,318 @@ #define _S64_STRLEN (1 + _U64_STRLEN) #define _UPTR_STRLEN (2 + 16 + 1) /* 64bit in hex with leading `0x` prefix */ +#define UK_STORE_ENTRY_ISSTATIC(entry) \ + ((entry)->flags & UK_STORE_ENTRY_FLAG_STATIC) + +#define OBJECT_ENTRY(e) \ + (__containerof(e, struct uk_store_object_entry, entry)) + +#define OBJECT(e) \ + (OBJECT_ENTRY(e)->object) + +struct uk_store_object_entry { + struct uk_store_entry entry; + struct uk_store_object *object; + struct uk_list_head list_head; +} __align8; + +/* The starting point of all dynamic objects for each library */ +static struct uk_list_head dynamic_heads[__UKLIBID_COUNT__] = { NULL, }; +static __spinlock dynamic_heads_lock = UK_SPINLOCK_INITIALIZER(); + #include -/** - * Releases an entry (decreases the refcount and sets the reference to NULL) - * If the refcount is 0 (it was also released by the creator), it is removed - * from the list and memory is freed - * - * @param p_entry pointer to the entry to release - */ -void -_uk_store_release_entry(const struct uk_store_entry *p_entry) +#define _UK_STORE_DYNAMIC_CREATE_TYPED(gen_type) \ + const struct uk_store_entry * \ + _uk_store_create_dynamic_entry_ ## gen_type( \ + struct uk_store_object *object, \ + __u64 entry_id, \ + const char *name, \ + uk_store_get_ ## gen_type ## _func_t get, \ + uk_store_set_ ## gen_type ## _func_t set) \ + { \ + struct uk_store_object_entry *new_object_entry; \ + \ + UK_ASSERT(object || name || object->a); \ + \ + new_object_entry = object->a->malloc(object->a, \ + sizeof(*new_object_entry)); \ + if (!new_object_entry) \ + return ERR2PTR(ENOMEM); \ + \ + new_object_entry->entry.name = object->a->malloc( \ + object->a, sizeof(*name) * (strlen(name) + 1)); \ + if (!new_object_entry->entry.name) { \ + object->a->free(object->a, new_object_entry); \ + return ERR2PTR(ENOMEM); \ + } \ + strcpy(new_object_entry->entry.name, name); \ + new_object_entry->entry.id = entry_id; \ + new_object_entry->entry.type = \ + UK_STORE_ENTRY_TYPE(gen_type); \ + new_object_entry->entry.get.gen_type = get; \ + new_object_entry->entry.set.gen_type = set; \ + new_object_entry->entry.flags = 0; \ + new_object_entry->object = object; \ + \ + uk_list_add(&(new_object_entry)->list_head, \ + &(object)->entry_head); \ + \ + return &new_object_entry->entry; \ + } + +/* Generate a function creator for each type */ +_UK_STORE_DYNAMIC_CREATE_TYPED(u8); +_UK_STORE_DYNAMIC_CREATE_TYPED(s8); +_UK_STORE_DYNAMIC_CREATE_TYPED(u16); +_UK_STORE_DYNAMIC_CREATE_TYPED(s16); +_UK_STORE_DYNAMIC_CREATE_TYPED(u32); +_UK_STORE_DYNAMIC_CREATE_TYPED(s32); +_UK_STORE_DYNAMIC_CREATE_TYPED(u64); +_UK_STORE_DYNAMIC_CREATE_TYPED(s64); +_UK_STORE_DYNAMIC_CREATE_TYPED(uptr); +_UK_STORE_DYNAMIC_CREATE_TYPED(charp); + +/* Capital types used internally */ +#define S8 __do_not_expand__ +#define U8 __do_not_expand__ +#define S16 __do_not_expand__ +#define U16 __do_not_expand__ +#define S32 __do_not_expand__ +#define U32 __do_not_expand__ +#define S64 __do_not_expand__ +#define U64 __do_not_expand__ +#define PTR __do_not_expand__ + +static void free_entry(const struct uk_store_entry *entry) { - if (UK_STORE_ENTRY_ISSTATIC(p_entry)) + struct uk_alloc *a = OBJECT(entry)->a; + + if (UK_STORE_ENTRY_ISSTATIC(entry)) return; + + a->free(a, entry->name); + a->free(a, OBJECT_ENTRY(entry)); } -const struct uk_store_entry * -_uk_store_get_static_entry(__u16 libid, __u64 entry_id) +static void release_entry(const struct uk_store_entry *entry) +{ + struct uk_store_object_entry *obj_entry; + + if (UK_STORE_ENTRY_ISSTATIC(entry)) + return; + + obj_entry = OBJECT_ENTRY(entry); + + uk_list_del(&obj_entry->list_head); + + free_entry(entry); +} + +static void free_object(struct uk_store_object *object) +{ + struct uk_store_object_entry *iter, *sec; + const struct uk_store_entry *entry; + + object->a->free(object->a, object->name); + + uk_list_for_each_entry_safe(iter, sec, + &object->entry_head, list_head) { + uk_list_del(&iter->list_head); + iter->object = NULL; + entry = &iter->entry; + release_entry(entry); + } +} + +static struct uk_store_object *get_obj_by_id(unsigned int lib_id, __u64 obj_id) +{ + struct uk_store_object *obj = NULL; + + uk_list_for_each_entry(obj, &dynamic_heads[lib_id], object_head) + if (obj->id == obj_id) + break; + + return obj; +} + +struct uk_store_object * +uk_store_obj_alloc(struct uk_alloc *a, __u64 id, const char *name, + const struct uk_store_entry *entries[], void *cookie) +{ + struct uk_store_object *new_object; + const struct uk_store_entry *e; + + UK_ASSERT(name); + UK_ASSERT(entries); + + new_object = a->malloc(a, sizeof(*new_object)); + if (!new_object) + return ERR2PTR(ENOMEM); + + new_object->name = a->malloc(a, sizeof(*name) * (strlen(name) + 1)); + if (!new_object->name) { + a->free(a, new_object); + return ERR2PTR(ENOMEM); + } + + strcpy(new_object->name, name); + + new_object->a = a; + new_object->id = id; + new_object->cookie = cookie; + + uk_refcount_init(&new_object->refcount, 1); + + UK_INIT_LIST_HEAD(&new_object->object_head); + UK_INIT_LIST_HEAD(&new_object->entry_head); + + for (__sz i = 0; entries[i]; i++) { + e = entries[i]; + switch (e->type) { + case UK_STORE_ENTRY_TYPE(s8): + _uk_store_create_dynamic_entry_s8(new_object, + e->id, + e->name, + e->get.s8, + e->set.s8); + break; + case UK_STORE_ENTRY_TYPE(u8): + _uk_store_create_dynamic_entry_u8(new_object, + e->id, + e->name, + e->get.u8, + e->set.u8); + break; + case UK_STORE_ENTRY_TYPE(s16): + _uk_store_create_dynamic_entry_s16(new_object, + e->id, + e->name, + e->get.s16, + e->set.s16); + break; + case UK_STORE_ENTRY_TYPE(u16): + _uk_store_create_dynamic_entry_u16(new_object, + e->id, + e->name, + e->get.u16, + e->set.u16); + break; + case UK_STORE_ENTRY_TYPE(s32): + _uk_store_create_dynamic_entry_s32(new_object, + e->id, + e->name, + e->get.s32, + e->set.s32); + break; + case UK_STORE_ENTRY_TYPE(u32): + _uk_store_create_dynamic_entry_u32(new_object, + e->id, + e->name, + e->get.u32, + e->set.u32); + break; + case UK_STORE_ENTRY_TYPE(s64): + _uk_store_create_dynamic_entry_s64(new_object, + e->id, + e->name, + e->get.s64, + e->set.s64); + break; + case UK_STORE_ENTRY_TYPE(u64): + _uk_store_create_dynamic_entry_u64(new_object, + e->id, + e->name, + e->get.u64, + e->set.u64); + break; + + case UK_STORE_ENTRY_TYPE(uptr): + _uk_store_create_dynamic_entry_uptr(new_object, + e->id, + e->name, + e->get.uptr, + e->set.uptr); + break; + case UK_STORE_ENTRY_TYPE(charp): + _uk_store_create_dynamic_entry_charp(new_object, + e->id, + e->name, + e->get.charp, + e->set.charp); + break; + default: + return ERR2PTR(EINVAL); + }; + } + + return new_object; +} + +int _uk_store_obj_add(__u16 library_id, struct uk_store_object *object) +{ + struct uk_store_event_data event_data; + + UK_ASSERT(object); + + if (!dynamic_heads[library_id].next) + UK_INIT_LIST_HEAD(&dynamic_heads[library_id]); + + object->libid = library_id; + uk_list_add(&object->object_head, &dynamic_heads[library_id]); + + /* Notify consumers */ + event_data = (struct uk_store_event_data) { + .library_id = object->libid, + .object_id = object->id + }; + + uk_raise_event(UKSTORE_EVENT_CREATE_OBJECT, &event_data); + + return 0; +} + +struct uk_store_object *uk_store_obj_acquire(__u16 library_id, __u64 object_id) +{ + struct uk_store_object *obj = NULL; + + if (!dynamic_heads[library_id].next) + return NULL; + + uk_spin_lock(&dynamic_heads_lock); + + obj = get_obj_by_id(library_id, object_id); + if (unlikely(!obj)) + goto out; + + uk_refcount_acquire(&obj->refcount); +out: + uk_spin_unlock(&dynamic_heads_lock); + + return obj; +} + +void uk_store_obj_release(struct uk_store_object *object) +{ + int res; + + UK_ASSERT(object); + + if (!dynamic_heads[object->libid].next) + return; + + uk_spin_lock(&dynamic_heads_lock); + + res = uk_refcount_release_if_not_last(&object->refcount); + if (!res) { + uk_list_del(&(object->object_head)); + free_object(object); + } + uk_spin_unlock(&dynamic_heads_lock); +} + +const struct uk_store_entry *uk_store_static_entry_get(__u16 libid, + __u64 entry_id) { struct uk_store_entry *entry = static_entries[2 * libid]; struct uk_store_entry *stop = static_entries[2 * libid + 1]; @@ -76,16 +373,22 @@ _uk_store_get_static_entry(__u16 libid, __u64 entry_id) return NULL; } -/* Capital types used internally */ -#define S8 __do_not_expand__ -#define U8 __do_not_expand__ -#define S16 __do_not_expand__ -#define U16 __do_not_expand__ -#define S32 __do_not_expand__ -#define U32 __do_not_expand__ -#define S64 __do_not_expand__ -#define U64 __do_not_expand__ -#define PTR __do_not_expand__ +const struct uk_store_entry * +uk_store_obj_entry_get(struct uk_store_object *object, __u64 entry_id) +{ + struct uk_store_object_entry *res = NULL; + + UK_ASSERT(object); + + uk_list_for_each_entry(res, &object->entry_head, list_head) + if (res->entry.id == entry_id) + break; + + if (res) + return &res->entry; + + return NULL; +} /** * Case defines used internally for shortening code @@ -170,6 +473,9 @@ _uk_store_set_u8(const struct uk_store_entry *e, __u8 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTUS(e, s8, S8, val, u8, cookie); SETCASE_UPCAST(e, u8, U8, val, u8, cookie); @@ -205,6 +511,9 @@ _uk_store_set_s8(const struct uk_store_entry *e, __s8 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_UPCAST(e, s8, S8, val, s8, cookie); SETCASE_UPCASTSU(e, u8, U8, val, s8, cookie); @@ -240,6 +549,9 @@ _uk_store_set_u16(const struct uk_store_entry *e, __u16 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTUS(e, s8, S8, val, u16, cookie); SETCASE_DOWNCASTUU(e, u8, U8, val, u16, cookie); @@ -274,6 +586,9 @@ _uk_store_set_s16(const struct uk_store_entry *e, __s16 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTSS(e, s8, S8, val, s16, cookie); SETCASE_DOWNCASTSU(e, u8, U8, val, s16, cookie); @@ -309,6 +624,9 @@ _uk_store_set_u32(const struct uk_store_entry *e, __u32 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTUS(e, s8, S8, val, u32, cookie); SETCASE_DOWNCASTUU(e, u8, U8, val, u32, cookie); @@ -344,6 +662,9 @@ _uk_store_set_s32(const struct uk_store_entry *e, __s32 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTSS(e, s8, S8, val, s32, cookie); SETCASE_DOWNCASTSU(e, u8, U8, val, s32, cookie); @@ -379,6 +700,9 @@ _uk_store_set_u64(const struct uk_store_entry *e, __u64 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTUS(e, s8, S8, val, u64, cookie); SETCASE_DOWNCASTUU(e, u8, U8, val, u64, cookie); @@ -414,6 +738,9 @@ _uk_store_set_s64(const struct uk_store_entry *e, __s64 val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTSS(e, s8, S8, val, s64, cookie); SETCASE_DOWNCASTSU(e, u8, U8, val, s64, cookie); @@ -449,6 +776,9 @@ _uk_store_set_uptr(const struct uk_store_entry *e, __uptr val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { SETCASE_DOWNCASTUS(e, s8, S8, val, uptr, cookie); SETCASE_DOWNCASTUU(e, u8, U8, val, uptr, cookie); @@ -485,6 +815,8 @@ _uk_store_set_charp(const struct uk_store_entry *e, const char *val) if (unlikely(e->set.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; switch (e->type) { case UK_STORE_ENTRY_TYPE(u8): { @@ -717,6 +1049,9 @@ _uk_store_get_u8(const struct uk_store_entry *e, __u8 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, U8, out, u8, cookie); GETCASE_UPCASTSU(e, s8, U8, out, u8, cookie); @@ -758,6 +1093,9 @@ _uk_store_get_s8(const struct uk_store_entry *e, __s8 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_DOWNCASTUS(e, u8, S8, out, s8, cookie); GETCASE_UPCAST(e, s8, S8, out, s8, cookie); @@ -799,6 +1137,9 @@ _uk_store_get_u16(const struct uk_store_entry *e, __u16 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, U16, out, u16, cookie); GETCASE_UPCASTSU(e, s8, U16, out, u16, cookie); @@ -840,6 +1181,9 @@ _uk_store_get_s16(const struct uk_store_entry *e, __s16 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, S16, out, s16, cookie); GETCASE_UPCAST(e, s8, S16, out, s16, cookie); @@ -881,6 +1225,9 @@ _uk_store_get_u32(const struct uk_store_entry *e, __u32 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, U32, out, u32, cookie); GETCASE_UPCASTSU(e, s8, U32, out, u32, cookie); @@ -922,6 +1269,9 @@ _uk_store_get_s32(const struct uk_store_entry *e, __s32 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, S32, out, s32, cookie); GETCASE_UPCAST(e, s8, S32, out, s32, cookie); @@ -963,6 +1313,9 @@ _uk_store_get_u64(const struct uk_store_entry *e, __u64 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, U64, out, u64, cookie); GETCASE_UPCASTSU(e, s8, U64, out, u64, cookie); @@ -1004,6 +1357,9 @@ _uk_store_get_s64(const struct uk_store_entry *e, __s64 *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, S64, out, s64, cookie); GETCASE_UPCAST(e, s8, S64, out, s64, cookie); @@ -1045,6 +1401,9 @@ _uk_store_get_uptr(const struct uk_store_entry *e, __uptr *out) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { GETCASE_UPCAST(e, u8, PTR, out, uptr, cookie); GETCASE_UPCASTSU(e, s8, PTR, out, uptr, cookie); @@ -1085,16 +1444,24 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) int ret; char *str; void *cookie = NULL; + struct uk_alloc *a = OBJECT(e)->a; UK_ASSERT(e); if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { case UK_STORE_ENTRY_TYPE(u8): { __u8 val; - str = calloc(_U8_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_U8_STRLEN, sizeof(char)); + else + str = a->calloc(a, _U8_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1109,7 +1476,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(s8): { __s8 val; - str = calloc(_S8_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_S8_STRLEN, sizeof(char)); + else + str = a->calloc(a, _S8_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1124,7 +1495,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(u16): { __u16 val; - str = calloc(_U16_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_U16_STRLEN, sizeof(char)); + else + str = a->calloc(a, _U16_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1139,7 +1514,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(s16): { __s16 val; - str = calloc(_S16_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_S16_STRLEN, sizeof(char)); + else + str = a->calloc(a, _S16_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1154,7 +1533,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(u32): { __u32 val; - str = calloc(_U32_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_U32_STRLEN, sizeof(char)); + else + str = a->calloc(a, _U32_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1169,7 +1552,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(s32): { __s32 val; - str = calloc(_S32_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_S32_STRLEN, sizeof(char)); + else + str = a->calloc(a, _S32_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1184,7 +1571,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(u64): { __u64 val; - str = calloc(_U64_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_U64_STRLEN, sizeof(char)); + else + str = a->calloc(a, _U64_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1199,7 +1590,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(s64): { __s64 val; - str = calloc(_S64_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_S64_STRLEN, sizeof(char)); + else + str = a->calloc(a, _S64_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1214,7 +1609,11 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) case UK_STORE_ENTRY_TYPE(uptr): { __uptr val; - str = calloc(_UPTR_STRLEN, sizeof(char)); + if (UK_STORE_ENTRY_ISSTATIC(e)) + str = calloc(_UPTR_STRLEN, sizeof(char)); + else + str = a->calloc(a, _UPTR_STRLEN, sizeof(char)); + if (unlikely(!str)) return -ENOMEM; @@ -1243,7 +1642,7 @@ _uk_store_get_charp(const struct uk_store_entry *e, char **out) int -uk_store_get_ncharp(const struct uk_store_entry *e, char *out, __sz maxlen) +_uk_store_get_ncharp(const struct uk_store_entry *e, char *out, __sz maxlen) { int ret; void *cookie = NULL; @@ -1253,6 +1652,9 @@ uk_store_get_ncharp(const struct uk_store_entry *e, char *out, __sz maxlen) if (unlikely(e->get.u8 == NULL)) return -EIO; + if (!UK_STORE_ENTRY_ISSTATIC(e)) + cookie = OBJECT(e)->cookie; + switch (e->type) { case UK_STORE_ENTRY_TYPE(u8): { __u8 val; @@ -1359,3 +1761,6 @@ uk_store_get_ncharp(const struct uk_store_entry *e, char *out, __sz maxlen) return -EINVAL; } } + +UK_EVENT(UKSTORE_EVENT_CREATE_OBJECT); +UK_EVENT(UKSTORE_EVENT_RELEASE_OBJECT);