fix atomics (finally)

This commit is contained in:
anna 2022-10-12 13:53:46 +02:00
parent 5d2539fc4a
commit e86ef2acbd
Signed by: fef
GPG key ID: EC22E476DC2D3D84
16 changed files with 72 additions and 70 deletions

View file

@ -20,7 +20,6 @@ configure_file(
target_sources(ardix_arch PRIVATE target_sources(ardix_arch PRIVATE
arch_init.c arch_init.c
atom.S atom.S
atomic.c
do_switch.S do_switch.S
entry.c entry.c
handle_fault.c handle_fault.c

View file

@ -1,34 +0,0 @@
/* See the end of this file for copyright, license, and warranty information. */
#include <ardix/atomic.h>
#include <ardix/atom.h>
static ATOM(atomic_context, 0);
void atomic_enter(void)
{
atom_get(&atomic_context);
}
void atomic_leave(void)
{
atom_put(&atomic_context);
}
int is_atomic(void)
{
return atom_read(&atomic_context);
}
/*
* This file is part of Ardix.
* Copyright (c) 2020, 2021 Felix Kopp <owo@fef.moe>.
*
* Ardix is non-violent software: you may only use, redistribute,
* and/or modify it under the terms of the CNPLv6+ as found in
* the LICENSE file in the source code root directory or at
* <https://git.pixie.town/thufie/CNPL>.
*
* Ardix comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPLv6+ for details.
*/

View file

@ -0,0 +1,28 @@
#pragma once
#include <ardix/types.h>
#include <toolchain.h>
static __always_inline word_t _atomic_enter(void)
{
word_t primask;
__asm__ volatile(
" mrs %0, primask \n"
" cpsid i \n"
: "=r"(primask));
return primask;
}
static __always_inline void _atomic_restore(word_t context)
{
if (!(context & 1))
__asm__ volatile("cpsie i");
}
static inline int _is_atomic(void)
{
int primask;
__asm__ volatile("mrs %0, primask" : "=r"(primask));
return primask & 1;
}

View file

@ -13,7 +13,7 @@ static __always_inline void atom_init(atom_t *atom, int val)
atom->_val = val; atom->_val = val;
} }
static __always_inline int atom_read(atom_t *atom) static __always_inline int atom_read(const atom_t *atom)
{ {
return atom->_val; return atom->_val;
} }

View file

@ -2,6 +2,10 @@
#pragma once #pragma once
#include <arch/atomic.h>
#include <toolchain.h>
/** /**
* Enter atomic context. * Enter atomic context.
* *
@ -9,13 +13,22 @@
* reference counter that is checked in the scheduler interrupt routine before * reference counter that is checked in the scheduler interrupt routine before
* performing the context switch. * performing the context switch.
*/ */
void atomic_enter(void); static __always_inline word_t atomic_enter(void)
{
return _atomic_enter();
}
/** Leave atomic context. */ /** Leave atomic context. */
void atomic_leave(void); static __always_inline void atomic_restore(word_t context)
{
_atomic_restore(context);
}
/** Return a nonzero value if the current process is in atomic context. */ /** Return a nonzero value if the current process is in atomic context. */
int is_atomic(void); static __always_inline int is_atomic(void)
{
return _is_atomic();
}
/* /*
* This file is part of Ardix. * This file is part of Ardix.

View file

@ -77,13 +77,13 @@ int devices_init(void);
int device_init(struct device *dev); int device_init(struct device *dev);
/** @brief Increment a device's reference counter. */ /** @brief Increment a device's reference counter. */
__always_inline void device_get(struct device *dev) static __always_inline void device_get(struct device *dev)
{ {
kent_get(&dev->kent); kent_get(&dev->kent);
} }
/** @brief Decrement a device's referece counter. */ /** @brief Decrement a device's referece counter. */
__always_inline void device_put(struct device *dev) static __always_inline void device_put(struct device *dev)
{ {
kent_put(&dev->kent); kent_put(&dev->kent);
} }

View file

@ -25,10 +25,16 @@ struct dmabuf {
struct dmabuf *dmabuf_create(struct device *dev, size_t len); struct dmabuf *dmabuf_create(struct device *dev, size_t len);
/** Increment a DMA buffer's reference counter. */ /** Increment a DMA buffer's reference counter. */
void dmabuf_get(struct dmabuf *buf); static __always_inline void dmabuf_get(struct dmabuf *buf)
{
kent_get(&buf->kent);
}
/** Decrement a DMA buffer's reference counter. */ /** Decrement a DMA buffer's reference counter. */
void dmabuf_put(struct dmabuf *buf); static __always_inline void dmabuf_put(struct dmabuf *buf)
{
kent_put(&buf->kent);
}
/* /*
* This file is part of Ardix. * This file is part of Ardix.

View file

@ -48,7 +48,10 @@ int kent_init(struct kent *kent);
* *
* @param kent: The kent. * @param kent: The kent.
*/ */
void kent_get(struct kent *kent); static __always_inline void kent_get(struct kent *kent)
{
atom_get(&kent->refcount);
}
/** /**
* Decrement the reference counter. * Decrement the reference counter.

View file

@ -104,12 +104,12 @@ struct kevent_listener *kevent_listener_add(enum kevent_kind kind,
*/ */
void kevent_listener_del(struct kevent_listener *listener); void kevent_listener_del(struct kevent_listener *listener);
__always_inline void kevent_get(struct kevent *event) static __always_inline void kevent_get(struct kevent *event)
{ {
kent_get(&event->kent); kent_get(&event->kent);
} }
__always_inline void kevent_put(struct kevent *event) static __always_inline void kevent_put(struct kevent *event)
{ {
kent_put(&event->kent); kent_put(&event->kent);
} }

View file

@ -39,14 +39,12 @@ __always_inline void spin_init(spin_t *spin)
__always_inline void spin_lock(spin_t *spin) __always_inline void spin_lock(spin_t *spin)
{ {
atomic_enter();
_spin_lock(&spin->lock); _spin_lock(&spin->lock);
} }
__always_inline void spin_unlock(spin_t *spin) __always_inline void spin_unlock(spin_t *spin)
{ {
_spin_unlock(&spin->lock); _spin_unlock(&spin->lock);
atomic_leave();
} }
__always_inline int spin_trylock(spin_t *spin) __always_inline int spin_trylock(spin_t *spin)

View file

@ -55,17 +55,17 @@ struct task {
pid_t pid; pid_t pid;
}; };
__always_inline void task_get(struct task *task) static __always_inline void task_get(struct task *task)
{ {
kent_get(&task->kent); kent_get(&task->kent);
} }
__always_inline void task_put(struct task *task) static __always_inline void task_put(struct task *task)
{ {
kent_put(&task->kent); kent_put(&task->kent);
} }
__always_inline struct task *task_parent(struct task *task) static inline struct task *task_parent(struct task *task)
{ {
if (task->pid == 0) if (task->pid == 0)
return NULL; return NULL;

View file

@ -40,16 +40,6 @@ struct dmabuf *dmabuf_create(struct device *dev, size_t len)
return buf; return buf;
} }
void dmabuf_get(struct dmabuf *buf)
{
kent_get(&buf->kent);
}
void dmabuf_put(struct dmabuf *buf)
{
kent_put(&buf->kent);
}
/* /*
* This file is part of Ardix. * This file is part of Ardix.
* Copyright (c) 2020, 2021 Felix Kopp <owo@fef.moe>. * Copyright (c) 2020, 2021 Felix Kopp <owo@fef.moe>.

View file

@ -33,11 +33,6 @@ int kent_init(struct kent *kent)
return 0; return 0;
} }
void kent_get(struct kent *kent)
{
atom_get(&kent->refcount);
}
void kent_put(struct kent *kent) void kent_put(struct kent *kent)
{ {
do { do {

View file

@ -296,7 +296,7 @@ void kfree(void *ptr)
if (!blk_is_alloc(blk)) if (!blk_is_alloc(blk))
__breakpoint; __breakpoint;
atomic_enter(); word_t context = atomic_enter();
atomic_heap_free += blk_get_size(blk); atomic_heap_free += blk_get_size(blk);
blk_clear_alloc(blk); blk_clear_alloc(blk);
blk = blk_try_merge(&atomic_heap, blk); blk = blk_try_merge(&atomic_heap, blk);
@ -305,7 +305,7 @@ void kfree(void *ptr)
memset(&blk->data[MIN_SIZE], 0xaa, blk_get_size(blk) - MIN_SIZE); memset(&blk->data[MIN_SIZE], 0xaa, blk_get_size(blk) - MIN_SIZE);
# endif # endif
atomic_leave(); atomic_restore(context);
} else { } else {
__breakpoint; __breakpoint;
} }

View file

@ -24,9 +24,11 @@ void mutex_lock(struct mutex *mutex)
.task = current, .task = current,
}; };
word_t context = atomic_enter();
spin_lock(&mutex->wait_queue_lock); spin_lock(&mutex->wait_queue_lock);
list_insert(&mutex->wait_queue, &entry.link); list_insert(&mutex->wait_queue, &entry.link);
spin_unlock(&mutex->wait_queue_lock); spin_unlock(&mutex->wait_queue_lock);
atomic_restore(context);
yield(TASK_LOCKWAIT); yield(TASK_LOCKWAIT);
} }
@ -36,12 +38,14 @@ void mutex_unlock(struct mutex *mutex)
{ {
struct mutex_wait *waiter = NULL; struct mutex_wait *waiter = NULL;
word_t context = atomic_enter();
spin_lock(&mutex->wait_queue_lock); spin_lock(&mutex->wait_queue_lock);
if (!list_is_empty(&mutex->wait_queue)) { if (!list_is_empty(&mutex->wait_queue)) {
waiter = list_first_entry(&mutex->wait_queue, struct mutex_wait, link); waiter = list_first_entry(&mutex->wait_queue, struct mutex_wait, link);
list_delete(&waiter->link); list_delete(&waiter->link);
} }
spin_unlock(&mutex->wait_queue_lock); spin_unlock(&mutex->wait_queue_lock);
atomic_restore(context);
if (waiter != NULL) { if (waiter != NULL) {
waiter->task->state = TASK_QUEUE; waiter->task->state = TASK_QUEUE;

View file

@ -152,7 +152,7 @@ static bool can_run(const struct task *task)
void schedule(void) void schedule(void)
{ {
atomic_enter(); word_t context = atomic_enter();
struct task *old = current; struct task *old = current;
pid_t nextpid = old->pid; pid_t nextpid = old->pid;
@ -186,7 +186,7 @@ void schedule(void)
new->last_tick = tick; new->last_tick = tick;
current = new; current = new;
atomic_leave(); atomic_restore(context);
if (old != new) if (old != new)
do_switch(old, new); do_switch(old, new);