Skip to content

Capability/kobject modifications for comments #239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 4 additions & 19 deletions kernel/generic/include/cap/cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,10 @@ typedef enum {
KOBJECT_TYPE_MAX
} kobject_type_t;

struct task;

struct call;
struct irq;
struct phone;
struct waitq;
struct kobject;

typedef struct kobject_ops {
void (*destroy)(void *);
void (*destroy)(struct kobject *);
} kobject_ops_t;

extern kobject_ops_t *kobject_ops[];
Expand All @@ -76,7 +71,7 @@ extern kobject_ops_t *kobject_ops[];

/*
* Everything in kobject_t except for the atomic reference count, the capability
* list and its lock is imutable.
* list and its lock is immutable.
*/
typedef struct kobject {
kobject_type_t type;
Expand All @@ -86,14 +81,6 @@ typedef struct kobject {
mutex_t caps_list_lock;
/** List of published capabilities associated with the kobject */
list_t caps_list;

union {
void *raw;
struct call *call;
struct irq *irq;
struct phone *phone;
struct waitq *waitq;
};
} kobject_t;

/*
Expand Down Expand Up @@ -140,9 +127,7 @@ extern kobject_t *cap_unpublish(struct task *, cap_handle_t, kobject_type_t);
extern void cap_revoke(kobject_t *);
extern void cap_free(struct task *, cap_handle_t);

extern kobject_t *kobject_alloc(unsigned int);
extern void kobject_free(kobject_t *);
extern void kobject_initialize(kobject_t *, kobject_type_t, void *);
extern void kobject_initialize(kobject_t *, kobject_type_t);
extern kobject_t *kobject_get(struct task *, cap_handle_t, kobject_type_t);
extern void kobject_add_ref(kobject_t *);
extern void kobject_put(kobject_t *);
Expand Down
2 changes: 0 additions & 2 deletions kernel/generic/include/ddi/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ typedef struct irq {
IRQ_SPINLOCK_EXTERN(irq_uspace_hash_table_lock);
extern hash_table_t irq_uspace_hash_table;

extern slab_cache_t *irq_cache;

extern inr_t last_inr;

extern void irq_init(size_t, size_t);
Expand Down
21 changes: 19 additions & 2 deletions kernel/generic/include/ipc/ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ typedef struct phone {
atomic_size_t active_calls;
/** User-defined label */
sysarg_t label;
kobject_t *kobject;
kobject_t kobject;
} phone_t;

typedef struct answerbox {
Expand Down Expand Up @@ -107,7 +107,7 @@ typedef struct answerbox {
} answerbox_t;

typedef struct call {
kobject_t *kobject;
kobject_t kobject;

/**
* Task link.
Expand Down Expand Up @@ -168,11 +168,28 @@ typedef struct call {
} call_t;

extern slab_cache_t *phone_cache;
extern slab_cache_t *irq_cache;

extern answerbox_t *ipc_box_0;

extern kobject_ops_t call_kobject_ops;

static inline phone_t *phone_from_kobject(kobject_t *kobject)
{
if (kobject)
return ((void *) kobject) - offsetof(phone_t, kobject);
else
return NULL;
}

static inline call_t *call_from_kobject(kobject_t *kobject)
{
if (kobject)
return ((void *) kobject) - offsetof(call_t, kobject);
else
return NULL;
}

extern void ipc_init(void);

extern call_t *ipc_call_alloc(void);
Expand Down
14 changes: 14 additions & 0 deletions kernel/generic/include/ipc/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@

extern kobject_ops_t irq_kobject_ops;

typedef struct {
kobject_t kobject;
irq_t irq;
} irq_kobject_t;

static inline irq_t *irq_from_kobject(kobject_t *kobject)
{
if (kobject) {
return &((irq_kobject_t *) kobject)->irq;
} else {
return NULL;
}
}

extern irq_ownership_t ipc_irq_top_half_claim(irq_t *);
extern void ipc_irq_top_half_handler(irq_t *);

Expand Down
20 changes: 2 additions & 18 deletions kernel/generic/src/cap/cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@
#define CAPS_SIZE (CAPS_LAST - CAPS_START + 1)

static slab_cache_t *cap_cache;
static slab_cache_t *kobject_cache;

kobject_ops_t *kobject_ops[KOBJECT_TYPE_MAX] = {
[KOBJECT_TYPE_CALL] = &call_kobject_ops,
Expand Down Expand Up @@ -155,8 +154,6 @@ void caps_init(void)
{
cap_cache = slab_cache_create("cap_t", sizeof(cap_t), 0, NULL,
NULL, 0);
kobject_cache = slab_cache_create("kobject_t", sizeof(kobject_t), 0,
NULL, NULL, 0);
}

/** Allocate the capability info structure
Expand Down Expand Up @@ -462,31 +459,19 @@ void cap_free(task_t *task, cap_handle_t handle)
mutex_unlock(&task->cap_info->lock);
}

kobject_t *kobject_alloc(unsigned int flags)
{
return slab_alloc(kobject_cache, flags);
}

void kobject_free(kobject_t *kobj)
{
slab_free(kobject_cache, kobj);
}

/** Initialize kernel object
*
* @param kobj Kernel object to initialize.
* @param type Type of the kernel object.
* @param raw Raw pointer to the encapsulated object.
*/
void kobject_initialize(kobject_t *kobj, kobject_type_t type, void *raw)
void kobject_initialize(kobject_t *kobj, kobject_type_t type)
{
refcount_init(&kobj->refcnt);

mutex_initialize(&kobj->caps_list_lock, MUTEX_PASSIVE);
list_initialize(&kobj->caps_list);

kobj->type = type;
kobj->raw = raw;
}

/** Get new reference to kernel object from capability
Expand Down Expand Up @@ -536,8 +521,7 @@ void kobject_add_ref(kobject_t *kobj)
void kobject_put(kobject_t *kobj)
{
if (refcount_down(&kobj->refcnt)) {
KOBJECT_OP(kobj)->destroy(kobj->raw);
kobject_free(kobj);
KOBJECT_OP(kobj)->destroy(kobj);
}
}

Expand Down
6 changes: 0 additions & 6 deletions kernel/generic/src/ddi/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@
#include <memw.h>
#include <arch.h>

slab_cache_t *irq_cache = NULL;

/** Spinlock protecting the kernel IRQ hash table
*
* This lock must be taken only when interrupts are disabled.
Expand Down Expand Up @@ -96,10 +94,6 @@ void irq_init(size_t inrs, size_t chains)
{
last_inr = inrs - 1;

irq_cache = slab_cache_create("irq_t", sizeof(irq_t), 0, NULL, NULL,
FRAME_ATOMIC);
assert(irq_cache);

hash_table_create(&irq_uspace_hash_table, chains, 0, &irq_ht_ops);
hash_table_create(&irq_kernel_hash_table, chains, 0, &irq_ht_ops);
}
Expand Down
50 changes: 22 additions & 28 deletions kernel/generic/src/ipc/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ answerbox_t *ipc_box_0 = NULL;
static slab_cache_t *call_cache;
static slab_cache_t *answerbox_cache;

slab_cache_t *irq_cache = NULL;
slab_cache_t *phone_cache = NULL;

/** Initialize a call structure.
Expand All @@ -86,16 +87,17 @@ static void _ipc_call_init(call_t *call)
call->sender = NULL;
call->callerbox = NULL;
call->buffer = NULL;
kobject_initialize(&call->kobject, KOBJECT_TYPE_CALL);
}

static void call_destroy(void *arg)
static void call_destroy(kobject_t *arg)
{
call_t *call = (call_t *) arg;
call_t *call = call_from_kobject(arg);

if (call->buffer)
free(call->buffer);
if (call->caller_phone)
kobject_put(call->caller_phone->kobject);
kobject_put(&call->caller_phone->kobject);
slab_free(call_cache, call);
}

Expand All @@ -113,21 +115,11 @@ kobject_ops_t call_kobject_ops = {
*/
call_t *ipc_call_alloc(void)
{
// TODO: Allocate call and kobject in single allocation

call_t *call = slab_alloc(call_cache, FRAME_ATOMIC);
if (!call)
return NULL;

kobject_t *kobj = kobject_alloc(0);
if (!kobj) {
slab_free(call_cache, call);
return NULL;
}

_ipc_call_init(call);
kobject_initialize(kobj, KOBJECT_TYPE_CALL, call);
call->kobject = kobj;

return call;
}
Expand Down Expand Up @@ -180,7 +172,7 @@ bool ipc_phone_connect(phone_t *phone, answerbox_t *box)

if (!connected) {
/* We still have phone->kobject's reference; drop it */
kobject_put(phone->kobject);
kobject_put(&phone->kobject);
}

return connected;
Expand All @@ -200,7 +192,7 @@ void ipc_phone_init(phone_t *phone, task_t *caller)
phone->state = IPC_PHONE_FREE;
atomic_store(&phone->active_calls, 0);
phone->label = 0;
phone->kobject = NULL;
kobject_initialize(&phone->kobject, KOBJECT_TYPE_PHONE);
}

/** Helper function to facilitate synchronous calls.
Expand Down Expand Up @@ -293,7 +285,7 @@ void _ipc_answer_free_call(call_t *call, bool selflocked)
if (call->forget) {
/* This is a forgotten call and call->sender is not valid. */
spinlock_unlock(&call->forget_lock);
kobject_put(call->kobject);
kobject_put(&call->kobject);
return;
} else {
/*
Expand Down Expand Up @@ -351,7 +343,7 @@ static void _ipc_call_actions_internal(phone_t *phone, call_t *call,
task_t *caller = phone->caller;

call->caller_phone = phone;
kobject_add_ref(phone->kobject);
kobject_add_ref(&phone->kobject);

if (preforget) {
call->forget = true;
Expand All @@ -361,7 +353,7 @@ static void _ipc_call_actions_internal(phone_t *phone, call_t *call,
atomic_inc(&call->callerbox->active_calls);
else
atomic_inc(&caller->answerbox.active_calls);
kobject_add_ref(phone->kobject);
kobject_add_ref(&phone->kobject);
call->sender = caller;
call->active = true;
spinlock_lock(&caller->active_calls_lock);
Expand Down Expand Up @@ -478,7 +470,7 @@ errno_t ipc_phone_hangup(phone_t *phone)
irq_spinlock_unlock(&box->lock, true);

/* Drop the answerbox reference */
kobject_put(phone->kobject);
kobject_put(&phone->kobject);

call_t *call = phone->hangup_call;
phone->hangup_call = NULL;
Expand Down Expand Up @@ -580,7 +572,7 @@ errno_t ipc_wait_for_call(answerbox_t *box, uint32_t usec, unsigned int flags,
list_remove(&request->ab_link);
atomic_dec(&request->caller_phone->active_calls);
atomic_dec(&box->active_calls);
kobject_put(request->caller_phone->kobject);
kobject_put(&request->caller_phone->kobject);
} else if (!list_empty(&box->calls)) {
/* Count received call */
call_cnt++;
Expand Down Expand Up @@ -696,14 +688,14 @@ void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box)

task_release(phone->caller);

kobject_put(phone->kobject);
kobject_put(&phone->kobject);

/* Must start again */
goto restart_phones;
}

mutex_unlock(&phone->lock);
kobject_put(phone->kobject);
kobject_put(&phone->kobject);
}

irq_spinlock_unlock(&box->lock, true);
Expand All @@ -727,18 +719,18 @@ static void ipc_forget_call(call_t *call)
* with it; to avoid working with a destroyed call_t structure, we
* must hold a reference to it.
*/
kobject_add_ref(call->kobject);
kobject_add_ref(&call->kobject);

spinlock_unlock(&call->forget_lock);
spinlock_unlock(&TASK->active_calls_lock);

atomic_dec(&call->caller_phone->active_calls);
atomic_dec(&TASK->answerbox.active_calls);
kobject_put(call->caller_phone->kobject);
kobject_put(&call->caller_phone->kobject);

SYSIPC_OP(request_forget, call);

kobject_put(call->kobject);
kobject_put(&call->kobject);
}

static void ipc_forget_all_active_calls(void)
Expand Down Expand Up @@ -776,7 +768,7 @@ static void ipc_forget_all_active_calls(void)

static bool phone_cap_cleanup_cb(cap_t *cap, void *arg)
{
ipc_phone_hangup(cap->kobject->phone);
ipc_phone_hangup(phone_from_kobject(cap->kobject));
kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
KOBJECT_TYPE_PHONE);
kobject_put(kobj);
Expand All @@ -797,7 +789,7 @@ static void ipc_wait_for_all_answered_calls(void)

SYSIPC_OP(answer_process, call);

kobject_put(call->kobject);
kobject_put(&call->kobject);

/*
* Now there may be some new phones and new hangup calls to
Expand Down Expand Up @@ -891,6 +883,8 @@ void ipc_init(void)
NULL, 0);
answerbox_cache = slab_cache_create("answerbox_t", sizeof(answerbox_t),
0, NULL, NULL, 0);
irq_cache = slab_cache_create("irq_t", sizeof(irq_kobject_t),
0, NULL, NULL, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, so irq_cache is now a cache of irq_kobject_t objects. Wasn't it the case that before there were also pure irq_t objects not visible by userspace and therefore not referencable by a capability?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they still exist. They just never used this slab for allocations. I think they are all just static.

Copy link
Contributor Author

@le-jzr le-jzr Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit it's mildly confusing, I should probably rename the slab.

}

static void ipc_print_call_list(list_t *list)
Expand Down Expand Up @@ -926,7 +920,7 @@ static void ipc_print_call_list(list_t *list)

static bool print_task_phone_cb(cap_t *cap, void *arg)
{
phone_t *phone = cap->kobject->phone;
phone_t *phone = phone_from_kobject(cap->kobject);

mutex_lock(&phone->lock);
if (phone->state != IPC_PHONE_FREE) {
Expand Down
Loading