stuff
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#include <zinnia/handle.h>
|
||||
#include <zinnia/rights.h>
|
||||
#include <zinnia/status.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <kernel/namespace.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
zn_status_t namespace_new(struct namespace** out) {
|
||||
if (!out)
|
||||
return ZN_ERR_INTERNAL;
|
||||
|
||||
struct namespace* namespace = mem_alloc(sizeof(struct namespace), 0);
|
||||
if (!namespace)
|
||||
return ZN_ERR_NO_MEMORY;
|
||||
|
||||
namespace->mutex = (struct mutex){0};
|
||||
namespace->next_handle = 1;
|
||||
HASHMAP_INIT(&namespace->descriptors);
|
||||
|
||||
*out = namespace;
|
||||
return ZN_OK;
|
||||
}
|
||||
|
||||
zn_status_t namespace_add_desc(struct namespace* namespace, struct namespace_desc desc, zn_handle_t* out) {
|
||||
if (!namespace)
|
||||
return ZN_ERR_INTERNAL;
|
||||
|
||||
// Skip over handles that are already in use (e.g. hard-coded handles).
|
||||
zn_handle_t handle;
|
||||
do {
|
||||
handle = atomic_fetch_add_explicit(&namespace->next_handle, 1, memory_order_acq_rel);
|
||||
if (handle <= ZN_HANDLE_INVALID)
|
||||
continue;
|
||||
} while (HASHMAP_GET(&namespace->descriptors, handle, hashmap_hash_default, hashmap_eq_default) != nullptr);
|
||||
|
||||
zn_status_t status =
|
||||
HASHMAP_INSERT(&namespace->descriptors, handle, desc, hashmap_hash_default, hashmap_eq_default);
|
||||
if (status != ZN_OK)
|
||||
return status;
|
||||
|
||||
*out = handle;
|
||||
return ZN_OK;
|
||||
}
|
||||
|
||||
zn_status_t namespace_add_desc_at(struct namespace* namespace, struct namespace_desc desc, zn_handle_t handle) {
|
||||
if (!namespace)
|
||||
return ZN_ERR_INTERNAL;
|
||||
if (handle <= ZN_HANDLE_INVALID)
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
// Fail if a descriptor already exists at this handle.
|
||||
if (HASHMAP_GET(&namespace->descriptors, handle, hashmap_hash_default, hashmap_eq_default) != nullptr)
|
||||
return ZN_ERR_ALREADY_EXISTS;
|
||||
|
||||
return HASHMAP_INSERT(&namespace->descriptors, handle, desc, hashmap_hash_default, hashmap_eq_default);
|
||||
}
|
||||
|
||||
zn_status_t namespace_get(struct namespace* namespace, zn_handle_t handle, struct namespace_desc* out) {
|
||||
if (!namespace)
|
||||
return ZN_ERR_INTERNAL;
|
||||
if (!out)
|
||||
return ZN_ERR_INTERNAL;
|
||||
|
||||
if (handle <= ZN_HANDLE_INVALID)
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
struct namespace_desc* desc =
|
||||
HASHMAP_GET(&namespace->descriptors, handle, hashmap_hash_default, hashmap_eq_default);
|
||||
if (!desc)
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
*out = *desc;
|
||||
return ZN_OK;
|
||||
}
|
||||
|
||||
zn_status_t namespace_del_desc(struct namespace* namespace, zn_handle_t handle) {
|
||||
if (!namespace)
|
||||
return ZN_ERR_INTERNAL;
|
||||
|
||||
if (handle <= ZN_HANDLE_INVALID)
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
if (!HASHMAP_REMOVE(&namespace->descriptors, handle, hashmap_hash_default, hashmap_eq_default))
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
return ZN_OK;
|
||||
}
|
||||
|
||||
zn_status_t namespace_clone_desc(
|
||||
struct namespace* ns,
|
||||
struct namespace_desc* desc,
|
||||
zn_rights_t cloned_rights,
|
||||
zn_handle_t* out
|
||||
) {
|
||||
// The source handle must have the clone right.
|
||||
if (!(desc->rights & ZN_RIGHT_CLONE))
|
||||
return ZN_ERR_BAD_PERMS;
|
||||
|
||||
// Determine the rights for the cloned handle.
|
||||
zn_rights_t new_rights;
|
||||
if (cloned_rights & ZN_RIGHTS_IDENTICAL) {
|
||||
new_rights = desc->rights;
|
||||
} else {
|
||||
// The requested rights must be a subset of the original rights.
|
||||
if (cloned_rights & ~desc->rights)
|
||||
return ZN_ERR_BAD_PERMS;
|
||||
new_rights = cloned_rights;
|
||||
}
|
||||
|
||||
// Create the cloned descriptor.
|
||||
struct namespace_desc new_desc = *desc;
|
||||
new_desc.rights = new_rights;
|
||||
|
||||
return namespace_add_desc(ns, new_desc, out);
|
||||
}
|
||||
Reference in New Issue
Block a user