diff --git a/kernel/generic/include/cap/cap.h b/kernel/generic/include/cap/cap.h index d74c020116..93eea8928b 100644 --- a/kernel/generic/include/cap/cap.h +++ b/kernel/generic/include/cap/cap.h @@ -36,13 +36,14 @@ #define KERN_CAP_H_ #include -#include -#include -#include #include +#include +#include +#include #include +#include #include -#include +#include typedef enum { CAP_STATE_FREE, @@ -58,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[]; @@ -75,24 +71,16 @@ 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; - atomic_size_t refcnt; + atomic_refcount_t refcnt; /** Mutex protecting caps_list */ 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; /* @@ -128,7 +116,8 @@ typedef struct cap_info { extern void caps_init(void); extern errno_t caps_task_alloc(struct task *); extern void caps_task_free(struct task *); -extern void caps_task_init(struct task *); +extern void caps_task_clear(struct task *task); +extern errno_t caps_task_init(struct task *); extern bool caps_apply_to_kobject_type(struct task *, kobject_type_t, bool (*)(cap_t *, void *), void *); @@ -138,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 *); diff --git a/kernel/generic/include/ddi/irq.h b/kernel/generic/include/ddi/irq.h index 64098e10af..e75f8643ce 100644 --- a/kernel/generic/include/ddi/irq.h +++ b/kernel/generic/include/ddi/irq.h @@ -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); diff --git a/kernel/generic/include/ipc/ipc.h b/kernel/generic/include/ipc/ipc.h index b0d2cd8a58..82e6c73539 100644 --- a/kernel/generic/include/ipc/ipc.h +++ b/kernel/generic/include/ipc/ipc.h @@ -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 { @@ -107,7 +107,7 @@ typedef struct answerbox { } answerbox_t; typedef struct call { - kobject_t *kobject; + kobject_t kobject; /** * Task link. @@ -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); diff --git a/kernel/generic/include/ipc/irq.h b/kernel/generic/include/ipc/irq.h index 676af6f580..41a1c2c605 100644 --- a/kernel/generic/include/ipc/irq.h +++ b/kernel/generic/include/ipc/irq.h @@ -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 *); diff --git a/kernel/generic/include/synch/syswaitq.h b/kernel/generic/include/synch/syswaitq.h index 9e42318060..7c71fa1b17 100644 --- a/kernel/generic/include/synch/syswaitq.h +++ b/kernel/generic/include/synch/syswaitq.h @@ -43,8 +43,6 @@ extern kobject_ops_t waitq_kobject_ops; extern void sys_waitq_init(void); -extern void sys_waitq_task_cleanup(void); - extern sys_errno_t sys_waitq_create(uspace_ptr_cap_waitq_handle_t); extern sys_errno_t sys_waitq_sleep(cap_waitq_handle_t, uint32_t, unsigned int); extern sys_errno_t sys_waitq_wakeup(cap_waitq_handle_t); diff --git a/kernel/generic/src/cap/cap.c b/kernel/generic/src/cap/cap.c index 21a35cce0f..02fcec126d 100644 --- a/kernel/generic/src/cap/cap.c +++ b/kernel/generic/src/cap/cap.c @@ -92,11 +92,10 @@ #include #define CAPS_START ((intptr_t) CAP_NIL + 1) -#define CAPS_SIZE (INT_MAX - (int) CAPS_START) -#define CAPS_LAST (CAPS_SIZE - 1) +#define CAPS_LAST ((intptr_t) INT_MAX - 1) +#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, @@ -124,18 +123,37 @@ static bool caps_key_equal(const void *key, const ht_link_t *item) return *handle == cap->handle; } +static void caps_remove_callback(ht_link_t *item) +{ + cap_t *cap = hash_table_get_inst(item, cap_t, caps_link); + + if (cap->kobject) { + kobject_t *kobj = cap->kobject; + + mutex_lock(&kobj->caps_list_lock); + cap->kobject = NULL; + list_remove(&cap->kobj_link); + mutex_unlock(&kobj->caps_list_lock); + + kobject_put(kobj); + } + + list_remove(&cap->type_link); + + slab_free(cap_cache, cap); +} + static const hash_table_ops_t caps_ops = { .hash = caps_hash, .key_hash = caps_key_hash, - .key_equal = caps_key_equal + .key_equal = caps_key_equal, + .remove_callback = caps_remove_callback, }; 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 @@ -147,32 +165,58 @@ errno_t caps_task_alloc(task_t *task) task->cap_info = (cap_info_t *) malloc(sizeof(cap_info_t)); if (!task->cap_info) return ENOMEM; - task->cap_info->handles = ra_arena_create(); - if (!task->cap_info->handles) - goto error_handles; - if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE)) - goto error_span; - if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops)) - goto error_span; - return EOK; -error_span: - ra_arena_destroy(task->cap_info->handles); -error_handles: - free(task->cap_info); - return ENOMEM; + if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops)) { + free(task->cap_info); + return ENOMEM; + } + + mutex_initialize(&task->cap_info->lock, MUTEX_RECURSIVE); + + task->cap_info->handles = NULL; + + for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++) + list_initialize(&task->cap_info->type_list[t]); + + return EOK; } /** Initialize the capability info structure * * @param task Task for which to initialize the info structure. */ -void caps_task_init(task_t *task) +errno_t caps_task_init(task_t *task) { - mutex_initialize(&task->cap_info->lock, MUTEX_RECURSIVE); + assert(task->cap_info); + assert(!task->cap_info->handles); + + task->cap_info->handles = ra_arena_create(); + if (!task->cap_info->handles) + return ENOMEM; + + if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE)) { + ra_arena_destroy(task->cap_info->handles); + return ENOMEM; + } + + return EOK; +} + +void caps_task_clear(task_t *task) +{ + mutex_lock(&task->cap_info->lock); + + hash_table_clear(&task->cap_info->caps); + + if (task->cap_info->handles) { + ra_arena_destroy(task->cap_info->handles); + task->cap_info->handles = NULL; + } for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++) list_initialize(&task->cap_info->type_list[t]); + + mutex_unlock(&task->cap_info->lock); } /** Deallocate the capability info structure @@ -182,7 +226,10 @@ void caps_task_init(task_t *task) void caps_task_free(task_t *task) { hash_table_destroy(&task->cap_info->caps); - ra_arena_destroy(task->cap_info->handles); + + if (task->cap_info->handles) + ra_arena_destroy(task->cap_info->handles); + free(task->cap_info); } @@ -299,8 +346,8 @@ errno_t cap_alloc(task_t *task, cap_handle_t *handle) void cap_publish(task_t *task, cap_handle_t handle, kobject_t *kobj) { - mutex_lock(&kobj->caps_list_lock); mutex_lock(&task->cap_info->lock); + mutex_lock(&kobj->caps_list_lock); cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED); assert(cap); cap->state = CAP_STATE_PUBLISHED; @@ -308,8 +355,8 @@ cap_publish(task_t *task, cap_handle_t handle, kobject_t *kobj) cap->kobject = kobj; list_append(&cap->kobj_link, &kobj->caps_list); list_append(&cap->type_link, &task->cap_info->type_list[kobj->type]); - mutex_unlock(&task->cap_info->lock); mutex_unlock(&kobj->caps_list_lock); + mutex_unlock(&task->cap_info->lock); } static void cap_unpublish_unsafe(cap_t *cap) @@ -339,18 +386,14 @@ kobject_t *cap_unpublish(task_t *task, cap_handle_t handle, kobject_type_t type) { kobject_t *kobj = NULL; -restart: mutex_lock(&task->cap_info->lock); cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED); if (cap) { if (cap->kobject->type == type) { /* Hand over cap's reference to kobj */ kobj = cap->kobject; - if (mutex_trylock(&kobj->caps_list_lock) != EOK) { - mutex_unlock(&task->cap_info->lock); - kobj = NULL; - goto restart; - } + + mutex_lock(&kobj->caps_list_lock); cap_unpublish_unsafe(cap); mutex_unlock(&kobj->caps_list_lock); } @@ -375,14 +418,24 @@ kobject_t *cap_unpublish(task_t *task, cap_handle_t handle, kobject_type_t type) void cap_revoke(kobject_t *kobj) { mutex_lock(&kobj->caps_list_lock); - list_foreach_safe(kobj->caps_list, cur, hlp) { - cap_t *cap = list_get_instance(cur, cap_t, kobj_link); - mutex_lock(&cap->task->cap_info->lock); + + while (!list_empty(&kobj->caps_list)) { + cap_t *cap = list_get_instance(list_first(&kobj->caps_list), cap_t, kobj_link); + + /* We're trying to acquire the two locks in reverse order. */ + if (mutex_trylock(&cap->task->cap_info->lock) != EOK) { + mutex_unlock(&kobj->caps_list_lock); + mutex_lock(&kobj->caps_list_lock); + continue; + } + cap_unpublish_unsafe(cap); /* Drop the reference for the unpublished capability */ kobject_put(kobj); + mutex_unlock(&cap->task->cap_info->lock); } + mutex_unlock(&kobj->caps_list_lock); } @@ -403,35 +456,22 @@ void cap_free(task_t *task, cap_handle_t handle) hash_table_remove_item(&task->cap_info->caps, &cap->caps_link); ra_free(task->cap_info->handles, cap_handle_raw(handle), 1); - slab_free(cap_cache, cap); 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) { - atomic_store(&kobj->refcnt, 1); + 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 @@ -454,7 +494,7 @@ kobject_get(struct task *task, cap_handle_t handle, kobject_type_t type) if (cap) { if (cap->kobject->type == type) { kobj = cap->kobject; - atomic_inc(&kobj->refcnt); + refcount_up(&kobj->refcnt); } } mutex_unlock(&task->cap_info->lock); @@ -468,7 +508,7 @@ kobject_get(struct task *task, cap_handle_t handle, kobject_type_t type) */ void kobject_add_ref(kobject_t *kobj) { - atomic_inc(&kobj->refcnt); + refcount_up(&kobj->refcnt); } /** Drop reference to kernel object @@ -480,9 +520,8 @@ void kobject_add_ref(kobject_t *kobj) */ void kobject_put(kobject_t *kobj) { - if (atomic_postdec(&kobj->refcnt) == 1) { - KOBJECT_OP(kobj)->destroy(kobj->raw); - kobject_free(kobj); + if (refcount_down(&kobj->refcnt)) { + KOBJECT_OP(kobj)->destroy(kobj); } } diff --git a/kernel/generic/src/ddi/irq.c b/kernel/generic/src/ddi/irq.c index cae1229a14..36ff5e2497 100644 --- a/kernel/generic/src/ddi/irq.c +++ b/kernel/generic/src/ddi/irq.c @@ -49,8 +49,6 @@ #include #include -slab_cache_t *irq_cache = NULL; - /** Spinlock protecting the kernel IRQ hash table * * This lock must be taken only when interrupts are disabled. @@ -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); } diff --git a/kernel/generic/src/ipc/ipc.c b/kernel/generic/src/ipc/ipc.c index bc09e0e4a2..39c397de37 100644 --- a/kernel/generic/src/ipc/ipc.c +++ b/kernel/generic/src/ipc/ipc.c @@ -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. @@ -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); } @@ -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; } @@ -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; @@ -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. @@ -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 { /* @@ -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; @@ -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); @@ -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; @@ -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++; @@ -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); @@ -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) @@ -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); @@ -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 @@ -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); } static void ipc_print_call_list(list_t *list) @@ -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) { diff --git a/kernel/generic/src/ipc/ipcrsc.c b/kernel/generic/src/ipc/ipcrsc.c index 55259cd8d1..642e5c0a6b 100644 --- a/kernel/generic/src/ipc/ipcrsc.c +++ b/kernel/generic/src/ipc/ipcrsc.c @@ -43,11 +43,11 @@ #include #include -static void phone_destroy(void *arg) +static void phone_destroy(kobject_t *arg) { - phone_t *phone = (phone_t *) arg; + phone_t *phone = phone_from_kobject(arg); if (phone->hangup_call) - kobject_put(phone->hangup_call->kobject); + kobject_put(&phone->hangup_call->kobject); slab_free(phone_cache, phone); } @@ -75,17 +75,11 @@ errno_t phone_alloc(task_t *task, bool publish, cap_phone_handle_t *phandle, cap_free(TASK, handle); return ENOMEM; } - kobject_t *kobj = kobject_alloc(FRAME_ATOMIC); - if (!kobj) { - cap_free(TASK, handle); - slab_free(phone_cache, phone); - return ENOMEM; - } + call_t *hcall = ipc_call_alloc(); if (!hcall) { cap_free(TASK, handle); slab_free(phone_cache, phone); - free(kobj); return ENOMEM; } @@ -93,15 +87,12 @@ errno_t phone_alloc(task_t *task, bool publish, cap_phone_handle_t *phandle, phone->state = IPC_PHONE_CONNECTING; phone->hangup_call = hcall; - kobject_initialize(kobj, KOBJECT_TYPE_PHONE, phone); - phone->kobject = kobj; - if (publish) - cap_publish(task, handle, kobj); + cap_publish(task, handle, &phone->kobject); *phandle = handle; if (kobject) - *kobject = kobj; + *kobject = &phone->kobject; } return rc; } diff --git a/kernel/generic/src/ipc/irq.c b/kernel/generic/src/ipc/irq.c index ed64595c44..77758131df 100644 --- a/kernel/generic/src/ipc/irq.c +++ b/kernel/generic/src/ipc/irq.c @@ -294,15 +294,15 @@ static void irq_hash_out(irq_t *irq) irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); } -static void irq_destroy(void *arg) +static void irq_destroy(kobject_t *arg) { - irq_t *irq = (irq_t *) arg; + irq_kobject_t *kobj = (irq_kobject_t *) arg; - irq_hash_out(irq); + irq_hash_out(&kobj->irq); /* Free up the IRQ code and associated structures. */ - code_free(irq->notif_cfg.code); - slab_free(irq_cache, irq); + code_free(kobj->irq.notif_cfg.code); + slab_free(irq_cache, kobj); } kobject_ops_t irq_kobject_ops = { @@ -349,18 +349,15 @@ errno_t ipc_irq_subscribe(answerbox_t *box, inr_t inr, sysarg_t imethod, return rc; } - irq_t *irq = (irq_t *) slab_alloc(irq_cache, FRAME_ATOMIC); - if (!irq) { + irq_kobject_t *kobj = slab_alloc(irq_cache, FRAME_ATOMIC); + if (!kobj) { cap_free(TASK, handle); return ENOMEM; } - kobject_t *kobject = kobject_alloc(FRAME_ATOMIC); - if (!kobject) { - cap_free(TASK, handle); - slab_free(irq_cache, irq); - return ENOMEM; - } + kobject_initialize(&kobj->kobject, KOBJECT_TYPE_IRQ); + + irq_t *irq = &kobj->irq; irq_initialize(irq); irq->inr = inr; @@ -384,8 +381,7 @@ errno_t ipc_irq_subscribe(answerbox_t *box, inr_t inr, sysarg_t imethod, irq_spinlock_unlock(&irq->lock, false); irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); - kobject_initialize(kobject, KOBJECT_TYPE_IRQ, irq); - cap_publish(TASK, handle, kobject); + cap_publish(TASK, handle, &kobj->kobject); return EOK; } @@ -404,9 +400,9 @@ errno_t ipc_irq_unsubscribe(answerbox_t *box, cap_irq_handle_t handle) if (!kobj) return ENOENT; - assert(kobj->irq->notif_cfg.answerbox == box); + assert(irq_from_kobject(kobj)->notif_cfg.answerbox == box); - irq_hash_out(kobj->irq); + irq_hash_out(irq_from_kobject(kobj)); kobject_put(kobj); cap_free(TASK, handle); diff --git a/kernel/generic/src/ipc/kbox.c b/kernel/generic/src/ipc/kbox.c index db3f5dc230..31b267bc4d 100644 --- a/kernel/generic/src/ipc/kbox.c +++ b/kernel/generic/src/ipc/kbox.c @@ -241,11 +241,11 @@ errno_t ipc_connect_kbox(task_id_t taskid, cap_phone_handle_t *out_phone) return rc; } - kobject_t *phone_obj = kobject_get(TASK, phone_handle, - KOBJECT_TYPE_PHONE); + phone_t *phone = phone_from_kobject( + kobject_get(TASK, phone_handle, KOBJECT_TYPE_PHONE)); /* Connect the newly allocated phone to the kbox */ /* Hand over phone_obj's reference to ipc_phone_connect() */ - (void) ipc_phone_connect(phone_obj->phone, &task->kb.box); + (void) ipc_phone_connect(phone, &task->kb.box); mutex_unlock(&task->kb.cleanup_lock); task_release(task); diff --git a/kernel/generic/src/ipc/ops/conctmeto.c b/kernel/generic/src/ipc/ops/conctmeto.c index 9ca21f0d7b..51992fabb1 100644 --- a/kernel/generic/src/ipc/ops/conctmeto.c +++ b/kernel/generic/src/ipc/ops/conctmeto.c @@ -87,7 +87,7 @@ static errno_t answer_preprocess(call_t *answer, ipc_data_t *olddata) kobject_add_ref(pobj); /* Set the recipient-assigned label */ - pobj->phone->label = ipc_get_arg5(&answer->data); + phone_from_kobject(pobj)->label = ipc_get_arg5(&answer->data); /* Restore phone handle in answer's ARG5 */ ipc_set_arg5(&answer->data, ipc_get_arg5(olddata)); @@ -95,7 +95,7 @@ static errno_t answer_preprocess(call_t *answer, ipc_data_t *olddata) /* If the user accepted the call, connect */ if (ipc_get_retval(&answer->data) == EOK) { /* Hand over reference from pobj to the answerbox */ - (void) ipc_phone_connect(pobj->phone, &TASK->answerbox); + (void) ipc_phone_connect(phone_from_kobject(pobj), &TASK->answerbox); } else { /* Drop the extra reference */ kobject_put(pobj); diff --git a/kernel/generic/src/ipc/ops/concttome.c b/kernel/generic/src/ipc/ops/concttome.c index 4622fabb08..3b768668f5 100644 --- a/kernel/generic/src/ipc/ops/concttome.c +++ b/kernel/generic/src/ipc/ops/concttome.c @@ -48,7 +48,7 @@ static int request_process(call_t *call, answerbox_t *box) /* * Set the sender-assigned label to the new phone. */ - pobj->phone->label = ipc_get_arg5(&call->data); + phone_from_kobject(pobj)->label = ipc_get_arg5(&call->data); } call->priv = (sysarg_t) pobj; ipc_set_arg5(&call->data, cap_handle_raw(phandle)); @@ -87,7 +87,7 @@ static errno_t answer_preprocess(call_t *answer, ipc_data_t *olddata) */ kobject_add_ref(pobj); - if (ipc_phone_connect(pobj->phone, + if (ipc_phone_connect(phone_from_kobject(pobj), &answer->sender->answerbox)) { /* Pass the reference to the capability */ cap_publish(TASK, phandle, pobj); diff --git a/kernel/generic/src/ipc/ops/stchngath.c b/kernel/generic/src/ipc/ops/stchngath.c index 290b80e7f3..2eb5edd206 100644 --- a/kernel/generic/src/ipc/ops/stchngath.c +++ b/kernel/generic/src/ipc/ops/stchngath.c @@ -44,26 +44,26 @@ static errno_t request_preprocess(call_t *call, phone_t *phone) { task_t *other_task_s; - kobject_t *sender_obj = kobject_get(TASK, - (cap_handle_t) ipc_get_arg5(&call->data), KOBJECT_TYPE_PHONE); - if (!sender_obj) + phone_t *sender_phone = phone_from_kobject(kobject_get(TASK, + (cap_handle_t) ipc_get_arg5(&call->data), KOBJECT_TYPE_PHONE)); + if (!sender_phone) return ENOENT; - mutex_lock(&sender_obj->phone->lock); - if (sender_obj->phone->state != IPC_PHONE_CONNECTED) { - mutex_unlock(&sender_obj->phone->lock); - kobject_put(sender_obj); + mutex_lock(&sender_phone->lock); + if (sender_phone->state != IPC_PHONE_CONNECTED) { + mutex_unlock(&sender_phone->lock); + kobject_put(&sender_phone->kobject); return EINVAL; } - other_task_s = sender_obj->phone->callee->task; + other_task_s = sender_phone->callee->task; - mutex_unlock(&sender_obj->phone->lock); + mutex_unlock(&sender_phone->lock); /* Remember the third party task hash. */ ipc_set_arg5(&call->data, (sysarg_t) other_task_s); - kobject_put(sender_obj); + kobject_put(&sender_phone->kobject); return EOK; } @@ -76,23 +76,23 @@ static errno_t answer_preprocess(call_t *answer, ipc_data_t *olddata) task_t *other_task_s; task_t *other_task_r; - kobject_t *recipient_obj = kobject_get(TASK, + phone_t *recipient_phone = phone_from_kobject(kobject_get(TASK, (cap_handle_t) ipc_get_arg1(&answer->data), - KOBJECT_TYPE_PHONE); - if (!recipient_obj) { + KOBJECT_TYPE_PHONE)); + if (!recipient_phone) { ipc_set_retval(&answer->data, ENOENT); return ENOENT; } - mutex_lock(&recipient_obj->phone->lock); - if (recipient_obj->phone->state != IPC_PHONE_CONNECTED) { - mutex_unlock(&recipient_obj->phone->lock); + mutex_lock(&recipient_phone->lock); + if (recipient_phone->state != IPC_PHONE_CONNECTED) { + mutex_unlock(&recipient_phone->lock); ipc_set_retval(&answer->data, EINVAL); - kobject_put(recipient_obj); + kobject_put(&recipient_phone->kobject); return EINVAL; } - other_task_r = recipient_obj->phone->callee->task; + other_task_r = recipient_phone->callee->task; other_task_s = (task_t *) ipc_get_arg5(olddata); /* @@ -113,8 +113,8 @@ static errno_t answer_preprocess(call_t *answer, ipc_data_t *olddata) ipc_set_retval(&answer->data, rc); } - mutex_unlock(&recipient_obj->phone->lock); - kobject_put(recipient_obj); + mutex_unlock(&recipient_phone->lock); + kobject_put(&recipient_phone->kobject); } return rc; diff --git a/kernel/generic/src/ipc/sysipc.c b/kernel/generic/src/ipc/sysipc.c index e14f4c0c13..838613492e 100644 --- a/kernel/generic/src/ipc/sysipc.c +++ b/kernel/generic/src/ipc/sysipc.c @@ -198,7 +198,7 @@ errno_t answer_preprocess(call_t *answer, ipc_data_t *olddata) irq_spinlock_lock(&phone->callee->lock, true); list_remove(&phone->link); /* Drop callee->connected_phones reference */ - kobject_put(phone->kobject); + kobject_put(&phone->kobject); phone->state = IPC_PHONE_SLAMMED; phone->label = 0; irq_spinlock_unlock(&phone->callee->lock, true); @@ -272,31 +272,32 @@ static int process_request(answerbox_t *box, call_t *call) errno_t ipc_req_internal(cap_phone_handle_t handle, ipc_data_t *data, sysarg_t priv) { - kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); - if (!kobj->phone) + phone_t *phone = phone_from_kobject( + kobject_get(TASK, handle, KOBJECT_TYPE_PHONE)); + if (!phone) return ENOENT; call_t *call = ipc_call_alloc(); if (!call) { - kobject_put(kobj); + kobject_put(&phone->kobject); return ENOMEM; } call->priv = priv; memcpy(call->data.args, data->args, sizeof(data->args)); - errno_t rc = request_preprocess(call, kobj->phone); + errno_t rc = request_preprocess(call, phone); if (!rc) { #ifdef CONFIG_UDEBUG udebug_stoppable_begin(); #endif - kobject_add_ref(call->kobject); - rc = ipc_call_sync(kobj->phone, call); + kobject_add_ref(&call->kobject); + rc = ipc_call_sync(phone, call); spinlock_lock(&call->forget_lock); bool forgotten = call->forget; spinlock_unlock(&call->forget_lock); - kobject_put(call->kobject); + kobject_put(&call->kobject); #ifdef CONFIG_UDEBUG udebug_stoppable_end(); @@ -311,7 +312,7 @@ ipc_req_internal(cap_phone_handle_t handle, ipc_data_t *data, sysarg_t priv) * its owners and are responsible for its * deallocation. */ - kobject_put(call->kobject); + kobject_put(&call->kobject); } else { /* * The call was forgotten and it changed hands. @@ -319,7 +320,7 @@ ipc_req_internal(cap_phone_handle_t handle, ipc_data_t *data, sysarg_t priv) */ assert(rc == EINTR); } - kobject_put(kobj); + kobject_put(&phone->kobject); return rc; } @@ -328,8 +329,8 @@ ipc_req_internal(cap_phone_handle_t handle, ipc_data_t *data, sysarg_t priv) ipc_set_retval(&call->data, rc); memcpy(data->args, call->data.args, sizeof(data->args)); - kobject_put(call->kobject); - kobject_put(kobj); + kobject_put(&call->kobject); + kobject_put(&phone->kobject); return EOK; } @@ -369,18 +370,20 @@ static int check_call_limit(phone_t *phone) sys_errno_t sys_ipc_call_async_fast(cap_phone_handle_t handle, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t label) { - kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); - if (!kobj) + phone_t *phone = phone_from_kobject( + kobject_get(TASK, handle, KOBJECT_TYPE_PHONE)); + + if (!phone) return ENOENT; - if (check_call_limit(kobj->phone)) { - kobject_put(kobj); + if (check_call_limit(phone)) { + kobject_put(&phone->kobject); return ELIMIT; } call_t *call = ipc_call_alloc(); if (!call) { - kobject_put(kobj); + kobject_put(&phone->kobject); return ENOMEM; } @@ -398,14 +401,14 @@ sys_errno_t sys_ipc_call_async_fast(cap_phone_handle_t handle, sysarg_t imethod, /* Set the user-defined label */ call->data.answer_label = label; - errno_t res = request_preprocess(call, kobj->phone); + errno_t res = request_preprocess(call, phone); if (!res) - ipc_call(kobj->phone, call); + ipc_call(phone, call); else - ipc_backsend_err(kobj->phone, call, res); + ipc_backsend_err(phone, call, res); - kobject_put(kobj); + kobject_put(&phone->kobject); return EOK; } @@ -421,40 +424,41 @@ sys_errno_t sys_ipc_call_async_fast(cap_phone_handle_t handle, sysarg_t imethod, sys_errno_t sys_ipc_call_async_slow(cap_phone_handle_t handle, uspace_ptr_ipc_data_t data, sysarg_t label) { - kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); - if (!kobj) + phone_t *phone = phone_from_kobject( + kobject_get(TASK, handle, KOBJECT_TYPE_PHONE)); + if (!phone) return ENOENT; - if (check_call_limit(kobj->phone)) { - kobject_put(kobj); + if (check_call_limit(phone)) { + kobject_put(&phone->kobject); return ELIMIT; } call_t *call = ipc_call_alloc(); if (!call) { - kobject_put(kobj); + kobject_put(&phone->kobject); return ENOMEM; } errno_t rc = copy_from_uspace(&call->data.args, data + offsetof(ipc_data_t, args), sizeof(call->data.args)); if (rc != EOK) { - kobject_put(call->kobject); - kobject_put(kobj); + kobject_put(&call->kobject); + kobject_put(&phone->kobject); return (sys_errno_t) rc; } /* Set the user-defined label */ call->data.answer_label = label; - errno_t res = request_preprocess(call, kobj->phone); + errno_t res = request_preprocess(call, phone); if (!res) - ipc_call(kobj->phone, call); + ipc_call(phone, call); else - ipc_backsend_err(kobj->phone, call, res); + ipc_backsend_err(phone, call, res); - kobject_put(kobj); + kobject_put(&phone->kobject); return EOK; } @@ -488,7 +492,7 @@ static sys_errno_t sys_ipc_forward_common(cap_call_handle_t chandle, if (!ckobj) return ENOENT; - call_t *call = ckobj->call; + call_t *call = call_from_kobject(ckobj); ipc_data_t old; bool need_old = answer_need_old(call); @@ -550,7 +554,7 @@ static sys_errno_t sys_ipc_forward_common(cap_call_handle_t chandle, } } - rc = ipc_forward(call, pkobj->phone, &TASK->answerbox, mode); + rc = ipc_forward(call, phone_from_kobject(pkobj), &TASK->answerbox, mode); if (rc != EOK) { after_forward = true; goto error; @@ -658,7 +662,7 @@ sys_errno_t sys_ipc_answer_fast(cap_call_handle_t chandle, sysarg_t retval, if (!kobj) return ENOENT; - call_t *call = kobj->call; + call_t *call = call_from_kobject(kobj); assert(!(call->flags & IPC_CALL_ANSWERED)); ipc_data_t saved_data; @@ -705,7 +709,7 @@ sys_errno_t sys_ipc_answer_slow(cap_call_handle_t chandle, uspace_ptr_ipc_data_t if (!kobj) return ENOENT; - call_t *call = kobj->call; + call_t *call = call_from_kobject(kobj); assert(!(call->flags & IPC_CALL_ANSWERED)); ipc_data_t saved_data; @@ -750,7 +754,7 @@ sys_errno_t sys_ipc_hangup(cap_phone_handle_t handle) if (!kobj) return ENOENT; - errno_t rc = ipc_phone_hangup(kobj->phone); + errno_t rc = ipc_phone_hangup(phone_from_kobject(kobj)); kobject_put(kobj); cap_free(TASK, handle); return rc; @@ -796,7 +800,7 @@ sys_errno_t sys_ipc_wait_for_call(uspace_ptr_ipc_data_t calldata, uint32_t usec, call->data.cap_handle = CAP_NIL; STRUCT_TO_USPACE(calldata, &call->data); - kobject_put(call->kobject); + kobject_put(&call->kobject); return EOK; } @@ -805,14 +809,14 @@ sys_errno_t sys_ipc_wait_for_call(uspace_ptr_ipc_data_t calldata, uint32_t usec, process_answer(call); if (call->flags & IPC_CALL_DISCARD_ANSWER) { - kobject_put(call->kobject); + kobject_put(&call->kobject); goto restart; } call->data.cap_handle = CAP_NIL; STRUCT_TO_USPACE(calldata, &call->data); - kobject_put(call->kobject); + kobject_put(&call->kobject); return EOK; } @@ -835,8 +839,8 @@ sys_errno_t sys_ipc_wait_for_call(uspace_ptr_ipc_data_t calldata, uint32_t usec, if (rc != EOK) goto error; - kobject_add_ref(call->kobject); - cap_publish(TASK, handle, call->kobject); + kobject_add_ref(&call->kobject); + cap_publish(TASK, handle, &call->kobject); return EOK; error: diff --git a/kernel/generic/src/proc/task.c b/kernel/generic/src/proc/task.c index 9ccb3a9b43..813d818d9b 100644 --- a/kernel/generic/src/proc/task.c +++ b/kernel/generic/src/proc/task.c @@ -200,6 +200,11 @@ task_t *task_create(as_t *as, const char *name) if (!task) return NULL; + if (caps_task_init(task) != EOK) { + slab_free(task_cache, task); + return NULL; + } + refcount_init(&task->refcount); task_create_arch(task); @@ -212,8 +217,6 @@ task_t *task_create(as_t *as, const char *name) task->ucycles = 0; task->kcycles = 0; - caps_task_init(task); - task->ipc_info.call_sent = 0; task->ipc_info.call_received = 0; task->ipc_info.answer_sent = 0; @@ -247,9 +250,9 @@ task_t *task_create(as_t *as, const char *name) return NULL; } - kobject_t *phone_obj = kobject_get(task, phone_handle, - KOBJECT_TYPE_PHONE); - (void) ipc_phone_connect(phone_obj->phone, ipc_box_0); + phone_t *phone = phone_from_kobject( + kobject_get(task, phone_handle, KOBJECT_TYPE_PHONE)); + (void) ipc_phone_connect(phone, ipc_box_0); } irq_spinlock_lock(&tasks_lock, true); @@ -287,6 +290,8 @@ static void task_destroy(task_t *task) */ as_release(task->as); + caps_task_clear(task); + slab_free(task_cache, task); } diff --git a/kernel/generic/src/proc/thread.c b/kernel/generic/src/proc/thread.c index 4f82db1018..382302ea74 100644 --- a/kernel/generic/src/proc/thread.c +++ b/kernel/generic/src/proc/thread.c @@ -443,7 +443,7 @@ void thread_exit(void) * */ ipc_cleanup(); - sys_waitq_task_cleanup(); + caps_task_clear(TASK); LOG("Cleanup of task %" PRIu64 " completed.", TASK->taskid); } } diff --git a/kernel/generic/src/synch/syswaitq.c b/kernel/generic/src/synch/syswaitq.c index 7642869635..e57c4d4a25 100644 --- a/kernel/generic/src/synch/syswaitq.c +++ b/kernel/generic/src/synch/syswaitq.c @@ -47,37 +47,26 @@ static slab_cache_t *waitq_cache; -static void waitq_destroy(void *arg) +typedef struct { + kobject_t kobject; + waitq_t waitq; +} waitq_kobject_t; + +static void waitq_destroy(kobject_t *arg) { - waitq_t *wq = (waitq_t *) arg; + waitq_kobject_t *wq = (waitq_kobject_t *) arg; slab_free(waitq_cache, wq); } kobject_ops_t waitq_kobject_ops = { - .destroy = waitq_destroy + .destroy = waitq_destroy, }; -static bool waitq_cap_cleanup_cb(cap_t *cap, void *arg) -{ - kobject_t *kobj = cap_unpublish(cap->task, cap->handle, - KOBJECT_TYPE_WAITQ); - kobject_put(kobj); - cap_free(cap->task, cap->handle); - return true; -} - /** Initialize the user waitq subsystem */ void sys_waitq_init(void) { - waitq_cache = slab_cache_create("waitq_t", sizeof(waitq_t), 0, NULL, - NULL, 0); -} - -/** Clean-up all waitq capabilities held by the exiting task */ -void sys_waitq_task_cleanup(void) -{ - caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_WAITQ, - waitq_cap_cleanup_cb, NULL); + waitq_cache = slab_cache_create("syswaitq_t", sizeof(waitq_kobject_t), + 0, NULL, NULL, 0); } /** Create a waitq for the current task @@ -89,35 +78,28 @@ void sys_waitq_task_cleanup(void) */ sys_errno_t sys_waitq_create(uspace_ptr_cap_waitq_handle_t whandle) { - waitq_t *wq = slab_alloc(waitq_cache, FRAME_ATOMIC); - if (!wq) + waitq_kobject_t *kobj = slab_alloc(waitq_cache, FRAME_ATOMIC); + if (!kobj) return (sys_errno_t) ENOMEM; - waitq_initialize(wq); - kobject_t *kobj = kobject_alloc(0); - if (!kobj) { - slab_free(waitq_cache, wq); - return (sys_errno_t) ENOMEM; - } - kobject_initialize(kobj, KOBJECT_TYPE_WAITQ, wq); + kobject_initialize(&kobj->kobject, KOBJECT_TYPE_WAITQ); + waitq_initialize(&kobj->waitq); cap_handle_t handle; errno_t rc = cap_alloc(TASK, &handle); if (rc != EOK) { - slab_free(waitq_cache, wq); - kobject_free(kobj); + slab_free(waitq_cache, kobj); return (sys_errno_t) rc; } rc = copy_to_uspace(whandle, &handle, sizeof(handle)); if (rc != EOK) { cap_free(TASK, handle); - kobject_free(kobj); - slab_free(waitq_cache, wq); + slab_free(waitq_cache, kobj); return (sys_errno_t) rc; } - cap_publish(TASK, handle, kobj); + cap_publish(TASK, handle, &kobj->kobject); return (sys_errno_t) EOK; } @@ -150,7 +132,8 @@ sys_errno_t sys_waitq_destroy(cap_waitq_handle_t whandle) sys_errno_t sys_waitq_sleep(cap_waitq_handle_t whandle, uint32_t timeout, unsigned int flags) { - kobject_t *kobj = kobject_get(TASK, whandle, KOBJECT_TYPE_WAITQ); + waitq_kobject_t *kobj = + (waitq_kobject_t *) kobject_get(TASK, whandle, KOBJECT_TYPE_WAITQ); if (!kobj) return (sys_errno_t) ENOENT; @@ -158,14 +141,14 @@ sys_errno_t sys_waitq_sleep(cap_waitq_handle_t whandle, uint32_t timeout, udebug_stoppable_begin(); #endif - errno_t rc = _waitq_sleep_timeout(kobj->waitq, timeout, + errno_t rc = _waitq_sleep_timeout(&kobj->waitq, timeout, SYNCH_FLAGS_INTERRUPTIBLE | flags); #ifdef CONFIG_UDEBUG udebug_stoppable_end(); #endif - kobject_put(kobj); + kobject_put(&kobj->kobject); return (sys_errno_t) rc; } @@ -178,13 +161,14 @@ sys_errno_t sys_waitq_sleep(cap_waitq_handle_t whandle, uint32_t timeout, */ sys_errno_t sys_waitq_wakeup(cap_waitq_handle_t whandle) { - kobject_t *kobj = kobject_get(TASK, whandle, KOBJECT_TYPE_WAITQ); + waitq_kobject_t *kobj = + (waitq_kobject_t *) kobject_get(TASK, whandle, KOBJECT_TYPE_WAITQ); if (!kobj) return (sys_errno_t) ENOENT; - waitq_wake_one(kobj->waitq); + waitq_wake_one(&kobj->waitq); - kobject_put(kobj); + kobject_put(&kobj->kobject); return (sys_errno_t) EOK; } diff --git a/kernel/generic/src/sysinfo/stats.c b/kernel/generic/src/sysinfo/stats.c index 138014f031..e589bfc52e 100644 --- a/kernel/generic/src/sysinfo/stats.c +++ b/kernel/generic/src/sysinfo/stats.c @@ -383,7 +383,7 @@ static void *get_stats_threads(struct sysinfo_item *item, size_t *size, */ static bool produce_stats_ipcc_cb(cap_t *cap, void *arg) { - phone_t *phone = cap->kobject->phone; + phone_t *phone = (phone_t *) cap->kobject; ipccs_state_t *state = (ipccs_state_t *) arg; if (state->counting) {