obj: object header is no longer allocated automatically
This commit is contained in:
10
dev/core.c
10
dev/core.c
@@ -2,6 +2,8 @@
|
||||
#include <socks/object.h>
|
||||
#include <socks/device.h>
|
||||
|
||||
#define DEVICE_CAST(p) OBJECT_C_CAST(struct device, dev_base, &device_type, p)
|
||||
|
||||
static struct device *root_device = NULL;
|
||||
static struct object_type device_type = {
|
||||
.ob_name = "device",
|
||||
@@ -20,10 +22,10 @@ kern_status_t device_init(void)
|
||||
kern_status_t set_root_device(struct device *dev)
|
||||
{
|
||||
if (root_device) {
|
||||
object_deref(object_header(root_device));
|
||||
object_deref(&root_device->dev_base);
|
||||
}
|
||||
|
||||
object_ref(object_header(dev));
|
||||
object_ref(&dev->dev_base);
|
||||
root_device = dev;
|
||||
|
||||
return KERN_OK;
|
||||
@@ -35,6 +37,6 @@ struct device *device_alloc(void)
|
||||
if (!dev_object) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return object_data(dev_object);
|
||||
|
||||
return DEVICE_CAST(dev_object);
|
||||
}
|
||||
|
||||
@@ -21,15 +21,15 @@ An object is made up of two distinct halves: the **header** and the
|
||||
system, while the data is the programmer-defined part of the object,
|
||||
and can be used however the object-creator wants.
|
||||
|
||||
Object behaviour is defined by an `object_type_t` instance.
|
||||
An `object_type_t` provides the object system with all the information
|
||||
Object behaviour is defined by a `struct object_type` instance.
|
||||
A `struct object_type` provides the object system with all the information
|
||||
it needs to instantiate and interact with your objects.
|
||||
|
||||
|
||||
The Object Header
|
||||
-----------------
|
||||
|
||||
The object header is defined in `include/socks/object.h` as `object_t`.
|
||||
The object header is defined in `include/socks/object.h` as `struct object`.
|
||||
It contains information that is used by the object system, and typically
|
||||
should not be directly accessed outside of the object system.
|
||||
|
||||
@@ -37,10 +37,10 @@ The contents of the object header include:
|
||||
|
||||
* `ob_magic`: A magic value used to identify active objects.
|
||||
Functions that retrieve an object's header from its data (and vice versa)
|
||||
do not have type checking (i.e. they convert between `object_t *` and `void *`
|
||||
do not have type checking (i.e. they convert between `struct object *` and `void *`
|
||||
using simple pointer arithmetic), so checking for this magic number helps
|
||||
protect against non-objects being passed to functions expecting objects.
|
||||
* `ob_type`: A pointer to the `object_type_t` that was used to create the
|
||||
* `ob_type`: A pointer to the `struct object_type` that was used to create the
|
||||
object. Outside of the object system, this can be used as a read-only
|
||||
way to query type information about an object.
|
||||
* `ob_lock`: A general-purpose per-object lock. This lock is *not* reserved
|
||||
@@ -56,35 +56,24 @@ The contents of the object header include:
|
||||
queue entry.
|
||||
|
||||
|
||||
The Object Data
|
||||
---------------
|
||||
|
||||
The object data section is the programmer-defined part of the object, and
|
||||
can be used for any purpose, although it is typically used as storage space
|
||||
for a C structure. For example the data section of a `task` object is used
|
||||
to store an instance of a `task_t` C structure containing the task data.
|
||||
|
||||
The object header and data are allocated together in a single contiguous
|
||||
chunk, with the data coming after the header. **However**, you should
|
||||
interactive with the object as if you don't know this. The only safe
|
||||
way to convert between an object header pointer and data pointer is to
|
||||
use the `object_header()` and `object_data()` functions respectively.
|
||||
|
||||
The object data pointer is guaranteed to be aligned on a `long` boundary.
|
||||
|
||||
When defining a C structure for use when creating objects, you should
|
||||
define a member of type `struct object` somewhere within the structure.
|
||||
It does not have to be the first member in the struct. The object system
|
||||
provides a number of macros to simplify converting a `struct object *`
|
||||
to a pointer of your structure.
|
||||
|
||||
The Object Type
|
||||
---------------
|
||||
|
||||
The object type defines the name, size, and behaviour of an object.
|
||||
It is defined using the `object_type_t` C structure.
|
||||
It is defined using the `struct object_type` C structure.
|
||||
|
||||
Some notable parts of `object_type_t` include:
|
||||
Some notable parts of `struct object_type` include:
|
||||
|
||||
* `ob_name`: Human-readable name of the object type. For example:
|
||||
"namespace", "set", "task", etc.
|
||||
* `ob_size`: The length of the data section of the object in bytes.
|
||||
* `ob_cache`: An instance of `vm_cache_t` from which objects of this
|
||||
* `ob_cache`: An instance of `struct vm_cache` from which objects of this
|
||||
type are allocated. This cache is initialised and managed by the
|
||||
object system on behalf of the programmer, so this can be ignored
|
||||
outside of the object system.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <socks/queue.h>
|
||||
#include <socks/status.h>
|
||||
#include <socks/object.h>
|
||||
|
||||
struct device;
|
||||
|
||||
@@ -67,6 +68,7 @@ struct bus_device {
|
||||
};
|
||||
|
||||
struct device {
|
||||
struct object dev_base;
|
||||
enum device_type dev_type;
|
||||
struct device *dev_parent;
|
||||
struct queue dev_children;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define SOCKS_KEXT_H_
|
||||
|
||||
#include <socks/status.h>
|
||||
#include <socks/object.h>
|
||||
#include <socks/compiler.h>
|
||||
#include <socks/btree.h>
|
||||
|
||||
@@ -69,6 +70,7 @@ struct kext_info {
|
||||
};
|
||||
|
||||
struct kext {
|
||||
struct object k_base;
|
||||
enum kext_flags k_flags;
|
||||
char k_ident[KEXT_IDENT_MAX];
|
||||
uint64_t k_ident_hash;
|
||||
|
||||
@@ -13,6 +13,13 @@ extern "C" {
|
||||
#define OBJECT_MAGIC 0xBADDCAFE
|
||||
#define OBJECT_NAME_MAX 64
|
||||
|
||||
#define OBJECT_CAST(to_type, to_type_member, p) \
|
||||
((to_type *)((uintptr_t)p) - offsetof(to_type, to_type_member))
|
||||
#define OBJECT_C_CAST(c_type, c_type_member, obj_type, objp) \
|
||||
OBJECT_IS_TYPE(objp, obj_type) ? OBJECT_CAST(c_type, c_type_member, (objp)) : NULL
|
||||
#define OBJECT_IS_TYPE(obj, type_ptr) \
|
||||
((obj)->ob_type == (type_ptr))
|
||||
|
||||
struct object;
|
||||
struct object_attrib;
|
||||
|
||||
@@ -63,6 +70,7 @@ extern kern_status_t object_type_unregister(struct object_type *p);
|
||||
|
||||
extern struct object_namespace *global_namespace(void);
|
||||
extern struct object_namespace *object_namespace_create(void);
|
||||
extern struct object *ns_header(struct object_namespace *ns);
|
||||
extern kern_status_t object_namespace_get_object(struct object_namespace *ns, const char *path, struct object **out);
|
||||
extern kern_status_t object_publish(struct object_namespace *ns, const char *path, struct object *obj);
|
||||
extern kern_status_t object_unpublish(struct object_namespace *ns, struct object *obj);
|
||||
@@ -72,8 +80,6 @@ extern struct object *object_ref(struct object *obj);
|
||||
extern void object_deref(struct object *obj);
|
||||
extern void object_lock(struct object *obj, unsigned long *flags);
|
||||
extern void object_unlock(struct object *obj, unsigned long flags);
|
||||
extern void *object_data(struct object *obj);
|
||||
extern struct object *object_header(void *p);
|
||||
static inline kern_status_t object_get(const char *path, struct object **out)
|
||||
{
|
||||
return object_namespace_get_object(global_namespace(), path, out);
|
||||
|
||||
@@ -53,6 +53,8 @@ enum sched_mode {
|
||||
};
|
||||
|
||||
struct task {
|
||||
struct object t_base;
|
||||
|
||||
struct task *t_parent;
|
||||
unsigned int t_id;
|
||||
enum task_state t_state;
|
||||
@@ -66,6 +68,8 @@ struct task {
|
||||
};
|
||||
|
||||
struct thread {
|
||||
struct object thr_base;
|
||||
|
||||
enum thread_state tr_state;
|
||||
enum thread_flags tr_flags;
|
||||
struct task *tr_parent;
|
||||
@@ -131,8 +135,8 @@ static inline void rq_unlock(struct runqueue *rq, unsigned long flags)
|
||||
extern struct runqueue *cpu_rq(unsigned int cpu);
|
||||
|
||||
extern struct task *task_alloc(void);
|
||||
static inline struct task *task_ref(struct task *task) { return (struct task *)object_data(object_ref(object_header(task))); }
|
||||
static inline void task_deref(struct task *task) { object_deref(object_header(task)); }
|
||||
static inline struct task *task_ref(struct task *task) { return OBJECT_CAST(struct task, t_base, object_ref(&task->t_base)); }
|
||||
static inline void task_deref(struct task *task) { object_deref(&task->t_base); }
|
||||
extern struct task *task_from_pid(unsigned int pid);
|
||||
extern struct task *kernel_task(void);
|
||||
extern struct task *idle_task(void);
|
||||
@@ -150,12 +154,12 @@ extern void end_charge_period(void);
|
||||
|
||||
static inline void task_lock_irqsave(struct task *task, unsigned long *flags)
|
||||
{
|
||||
object_lock(object_header(task), flags);
|
||||
object_lock(&task->t_base, flags);
|
||||
}
|
||||
|
||||
static inline void task_unlock_irqrestore(struct task *task, unsigned long flags)
|
||||
{
|
||||
object_unlock(object_header(task), flags);
|
||||
object_unlock(&task->t_base, flags);
|
||||
}
|
||||
|
||||
extern struct thread *thread_alloc(void);
|
||||
|
||||
18
kxld/kext.c
18
kxld/kext.c
@@ -5,13 +5,17 @@
|
||||
#include <socks/object.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define KEXT_CAST(p) OBJECT_C_CAST(struct kext, k_base, &kext_type, p)
|
||||
|
||||
static spin_lock_t kext_tree_lock = SPIN_LOCK_INIT;
|
||||
static struct object *kext_set;
|
||||
struct btree kext_tree;
|
||||
|
||||
static struct object_type kext_type;
|
||||
|
||||
static kern_status_t kext_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
|
||||
{
|
||||
struct kext *kext = object_data(obj);
|
||||
struct kext *kext = KEXT_CAST(obj);
|
||||
strncpy(out, kext->k_ident, OBJECT_NAME_MAX - 1);
|
||||
out[OBJECT_NAME_MAX - 1] = 0;
|
||||
return KERN_OK;
|
||||
@@ -19,7 +23,7 @@ static kern_status_t kext_query_name(struct object *obj, char out[OBJECT_NAME_MA
|
||||
|
||||
static kern_status_t kext_destroy(struct object *obj)
|
||||
{
|
||||
struct kext *kext = object_data(obj);
|
||||
struct kext *kext = KEXT_CAST(obj);
|
||||
if (kext->k_dependencies) {
|
||||
kfree(kext->k_dependencies);
|
||||
}
|
||||
@@ -103,7 +107,7 @@ struct kext *kext_get_by_id(const char *ident)
|
||||
|
||||
struct kext *kext = kext_get(ident);
|
||||
if (kext) {
|
||||
struct object *kext_obj = object_header(kext);
|
||||
struct object *kext_obj = &kext->k_base;
|
||||
object_ref(kext_obj);
|
||||
}
|
||||
|
||||
@@ -126,12 +130,12 @@ struct kext *kext_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return object_data(kext_obj);
|
||||
return KEXT_CAST(kext_obj);
|
||||
}
|
||||
|
||||
void kext_release(struct kext *kext)
|
||||
{
|
||||
object_deref(object_header(kext));
|
||||
object_deref(&kext->k_base);
|
||||
}
|
||||
|
||||
kern_status_t kext_register(struct kext *kext)
|
||||
@@ -145,8 +149,8 @@ kern_status_t kext_register(struct kext *kext)
|
||||
return KERN_NAME_EXISTS;
|
||||
}
|
||||
|
||||
struct object *kext_obj = object_header(kext);
|
||||
object_ref(object_header(kext));
|
||||
struct object *kext_obj = &kext->k_base;
|
||||
object_ref(kext_obj);
|
||||
kext_add(kext);
|
||||
|
||||
set_add_object(kext_set, kext_obj);
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include <socks/object.h>
|
||||
|
||||
#define NAMESPACE_CAST(p) OBJECT_C_CAST(struct object_namespace, ns_base, &ns_type, p)
|
||||
|
||||
static struct object_type ns_type;
|
||||
static struct object_namespace *global_ns;
|
||||
|
||||
struct object_namespace {
|
||||
/* root directory set object */
|
||||
struct object ns_base;
|
||||
struct object *ns_root;
|
||||
};
|
||||
|
||||
@@ -16,13 +20,13 @@ static kern_status_t ns_query_name(struct object *obj, char out[OBJECT_NAME_MAX]
|
||||
|
||||
static kern_status_t ns_get_child_at(struct object *obj, size_t at, struct object **out)
|
||||
{
|
||||
struct object_namespace *ns = object_data(obj);
|
||||
struct object_namespace *ns = NAMESPACE_CAST(obj);
|
||||
return object_get_child_at(ns->ns_root, at, out);
|
||||
}
|
||||
|
||||
static kern_status_t ns_get_child_named(struct object *obj, const char *name, struct object **out)
|
||||
{
|
||||
struct object_namespace *ns = object_data(obj);
|
||||
struct object_namespace *ns = NAMESPACE_CAST(obj);
|
||||
return object_get_child_named(ns->ns_root, name, out);
|
||||
}
|
||||
|
||||
@@ -36,7 +40,6 @@ static struct object_type ns_type = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
void init_global_namespace(void)
|
||||
{
|
||||
object_type_register(&ns_type);
|
||||
@@ -51,7 +54,7 @@ struct object_namespace *global_namespace(void)
|
||||
struct object_namespace *object_namespace_create(void)
|
||||
{
|
||||
struct object *ns_object = object_create(&ns_type);
|
||||
struct object_namespace *ns = object_data(ns_object);
|
||||
struct object_namespace *ns = NAMESPACE_CAST(ns_object);
|
||||
ns->ns_root = set_create("/");
|
||||
return ns;
|
||||
}
|
||||
@@ -93,6 +96,11 @@ static void cleanup_object_path(char *path, size_t len, size_t *parts)
|
||||
path[final_len] = 0;
|
||||
}
|
||||
|
||||
struct object *ns_header(struct object_namespace *ns)
|
||||
{
|
||||
return &ns->ns_base;
|
||||
}
|
||||
|
||||
kern_status_t object_publish(struct object_namespace *ns, const char *path, struct object *obj)
|
||||
{
|
||||
if (*path != '/') {
|
||||
|
||||
@@ -22,7 +22,7 @@ kern_status_t object_type_register(struct object_type *p)
|
||||
spin_unlock_irqrestore(&object_types_lock, flags);
|
||||
|
||||
p->ob_cache.c_name = p->ob_name;
|
||||
p->ob_cache.c_obj_size = sizeof(struct object) + p->ob_size;
|
||||
p->ob_cache.c_obj_size = p->ob_size;
|
||||
p->ob_cache.c_page_order = VM_PAGE_16K;
|
||||
|
||||
vm_cache_init(&p->ob_cache);
|
||||
|
||||
31
obj/set.c
31
obj/set.c
@@ -1,22 +1,27 @@
|
||||
#include <socks/object.h>
|
||||
|
||||
#define SET_CAST(p) OBJECT_C_CAST(struct set, s_base, &set_type, p)
|
||||
|
||||
struct set {
|
||||
struct object s_base;
|
||||
struct queue s_list;
|
||||
char s_name[OBJECT_NAME_MAX];
|
||||
};
|
||||
|
||||
static struct object_type set_type;
|
||||
|
||||
static kern_status_t set_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
|
||||
{
|
||||
struct set *set = object_data(obj);
|
||||
struct set *set = SET_CAST(obj);
|
||||
strncpy(out, set->s_name, OBJECT_NAME_MAX - 1);
|
||||
out[OBJECT_NAME_MAX - 1] = 0;
|
||||
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static kern_status_t set_get_child_at(struct object *obj, size_t at, struct object **out)
|
||||
{
|
||||
struct set *set = object_data(obj);
|
||||
struct set *set = SET_CAST(obj);
|
||||
size_t i = 0;
|
||||
queue_foreach(struct object, child, &set->s_list, ob_list) {
|
||||
if (i == at) {
|
||||
@@ -26,15 +31,15 @@ static kern_status_t set_get_child_at(struct object *obj, size_t at, struct obje
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return KERN_NO_ENTRY;
|
||||
}
|
||||
|
||||
static kern_status_t set_get_child_named(struct object *obj, const char *name, struct object **out)
|
||||
{
|
||||
struct set *set = object_data(obj);
|
||||
struct set *set = SET_CAST(obj);
|
||||
char child_name[OBJECT_NAME_MAX];
|
||||
|
||||
|
||||
queue_foreach(struct object, child, &set->s_list, ob_list) {
|
||||
kern_status_t status = object_query_name(child, child_name);
|
||||
if (status != KERN_OK) {
|
||||
@@ -46,7 +51,7 @@ static kern_status_t set_get_child_named(struct object *obj, const char *name, s
|
||||
return KERN_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return KERN_NO_ENTRY;
|
||||
}
|
||||
|
||||
@@ -72,7 +77,7 @@ struct object *set_create(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct set *set = object_data(set_obj);
|
||||
struct set *set = SET_CAST(set_obj);
|
||||
set->s_list = QUEUE_INIT;
|
||||
strncpy(set->s_name, name, sizeof set->s_name - 1);
|
||||
set->s_name[sizeof set->s_name - 1] = 0;
|
||||
@@ -85,12 +90,12 @@ kern_status_t set_add_object(struct object *set_obj, struct object *obj)
|
||||
if (!object_is_set(set_obj)) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
struct set *set = object_data(set_obj);
|
||||
|
||||
struct set *set = SET_CAST(set_obj);
|
||||
|
||||
char child_name[OBJECT_NAME_MAX];
|
||||
char obj_name[OBJECT_NAME_MAX];
|
||||
|
||||
|
||||
kern_status_t status = object_query_name(obj, obj_name);
|
||||
if (status != KERN_OK) {
|
||||
return status;
|
||||
@@ -114,8 +119,8 @@ kern_status_t set_remove_object(struct object *set_obj, struct object *obj)
|
||||
if (!object_is_set(set_obj)) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
struct set *set = object_data(set_obj);
|
||||
|
||||
struct set *set = SET_CAST(set_obj);
|
||||
queue_delete(&set->s_list, &obj->ob_list);
|
||||
object_deref(obj);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <socks/cpu.h>
|
||||
#include <socks/libc/stdio.h>
|
||||
|
||||
#define TASK_CAST(p) OBJECT_C_CAST(struct task, t_base, &task_type, p)
|
||||
|
||||
static struct object_type task_type = {
|
||||
.ob_name = "task",
|
||||
.ob_size = sizeof(struct task),
|
||||
@@ -144,7 +146,7 @@ struct task *task_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct task *t = object_data(task_obj);
|
||||
struct task *t = TASK_CAST(task_obj);
|
||||
memset(t, 0x00, sizeof *t);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <socks/cpu.h>
|
||||
#include <socks/machine/thread.h>
|
||||
|
||||
#define THREAD_CAST(p) OBJECT_C_CAST(struct thread, thr_base, &thread_type, p)
|
||||
|
||||
static struct object_type thread_type = {
|
||||
.ob_name = "thread",
|
||||
.ob_size = sizeof(struct thread),
|
||||
@@ -20,7 +22,7 @@ struct thread *thread_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct thread *t = object_data(thread_obj);
|
||||
struct thread *t = THREAD_CAST(thread_obj);
|
||||
memset(t, 0x00, sizeof *t);
|
||||
return t;
|
||||
}
|
||||
|
||||
15
test/obj.c
15
test/obj.c
@@ -3,13 +3,18 @@
|
||||
#include <socks/init.h>
|
||||
#include <socks/libc/stdio.h>
|
||||
|
||||
#define TEST_CAST(p) OBJECT_C_CAST(struct test_object, base, &test_type, p)
|
||||
|
||||
struct test_object {
|
||||
struct object base;
|
||||
char name[OBJECT_NAME_MAX];
|
||||
};
|
||||
|
||||
static struct object_type test_type;
|
||||
|
||||
static kern_status_t test_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
|
||||
{
|
||||
struct test_object *test = object_data(obj);
|
||||
struct test_object *test = TEST_CAST(obj);
|
||||
strncpy(out, test->name, OBJECT_NAME_MAX);
|
||||
out[OBJECT_NAME_MAX - 1] = 0;
|
||||
return KERN_OK;
|
||||
@@ -37,10 +42,10 @@ static void print_object_tree(struct object *obj, int depth)
|
||||
|
||||
len += snprintf(msg + len, sizeof msg - len, "%s", name);
|
||||
printk(msg);
|
||||
|
||||
|
||||
struct object *child = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
|
||||
while (1) {
|
||||
kern_status_t status = object_get_child_at(obj, i, &child);
|
||||
if (status != KERN_OK) {
|
||||
@@ -58,7 +63,7 @@ static int run_obj_tests(void)
|
||||
object_type_register(&test_type);
|
||||
|
||||
struct object *test_obj = object_create(&test_type);
|
||||
struct test_object *test = object_data(test_obj);
|
||||
struct test_object *test = TEST_CAST(test_obj);
|
||||
snprintf(test->name, sizeof test->name, "object1");
|
||||
kern_status_t status = object_publish(global_namespace(), "/misc/objects", test_obj);
|
||||
if (status == KERN_OK) {
|
||||
@@ -73,7 +78,7 @@ static int run_obj_tests(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
print_object_tree(object_header(global_namespace()), 0);
|
||||
print_object_tree(ns_header(global_namespace()), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user