diff --git a/include/kernel/futex.h b/include/kernel/futex.h new file mode 100644 index 0000000..be21028 --- /dev/null +++ b/include/kernel/futex.h @@ -0,0 +1,26 @@ +#ifndef KERNEL_FUTEX_H_ +#define KERNEL_FUTEX_H_ + +#include +#include +#include + +struct address_space; + +typedef phys_addr_t futex_key_t; + +struct futex { + struct btree_node f_node; + futex_key_t f_key; + struct waitqueue f_waiters; +}; + +extern kern_status_t futex_init(void); +extern kern_status_t futex_get( + struct address_space *space, + kern_futex_t *futex, + futex_key_t *out); +extern kern_status_t futex_wait(futex_key_t futex, kern_futex_t new_val); +extern kern_status_t futex_wake(futex_key_t futex, size_t nwaiters); + +#endif diff --git a/kernel/futex.c b/kernel/futex.c new file mode 100644 index 0000000..2cb38b8 --- /dev/null +++ b/kernel/futex.c @@ -0,0 +1,70 @@ +#include +#include +#include + +enum futex_flags { + FUTEX_CREATE = 0x01u, +}; + +static struct btree futex_list = {0}; +static spin_lock_t futex_list_lock = SPIN_LOCK_INIT; + +static struct vm_cache futex_cache = { + .c_name = "futex", + .c_obj_size = sizeof(struct futex), +}; + +BTREE_DEFINE_SIMPLE_INSERT(struct futex, f_node, f_key, put_futex) +BTREE_DEFINE_SIMPLE_GET(struct futex, futex_key_t, f_node, f_key, get_futex) + +kern_status_t futex_init(void) +{ + vm_cache_init(&futex_cache); + return KERN_OK; +} + +static struct futex *get_data(futex_key_t key, enum futex_flags flags) +{ + spin_lock(&futex_list_lock); + struct futex *futex = get_futex(&futex_list, key); + spin_unlock(&futex_list_lock); + + if (!futex && !(flags & FUTEX_CREATE)) { + return NULL; + } + + futex = vm_cache_alloc(&futex_cache, VM_NORMAL); + futex->f_key = key; + + spin_lock(&futex_list_lock); + put_futex(&futex_list, futex); + spin_unlock(&futex_list_lock); + + return futex; +} + +kern_status_t futex_get( + struct address_space *space, + kern_futex_t *futex, + futex_key_t *out) +{ + unsigned long flags; + address_space_lock_irqsave(space, &flags); + kern_status_t status = address_space_translate( + space, + (virt_addr_t)futex, + out, + &flags); + address_space_unlock_irqrestore(space, flags); + return status; +} + +kern_status_t futex_wait(futex_key_t futex, kern_futex_t new_val) +{ + return KERN_UNIMPLEMENTED; +} + +kern_status_t futex_wake(futex_key_t futex, size_t nwaiters) +{ + return KERN_UNIMPLEMENTED; +} diff --git a/libmango/include-user/mango/futex.h b/libmango/include-user/mango/futex.h new file mode 100644 index 0000000..e69de29 diff --git a/libmango/include/mango/types.h b/libmango/include/mango/types.h index f9b49ad..ab1bfeb 100644 --- a/libmango/include/mango/types.h +++ b/libmango/include/mango/types.h @@ -46,20 +46,16 @@ #define IOVEC(p, len) \ { \ - .io_base = (virt_addr_t)(p), \ - .io_len = (len), \ + .io_base = (virt_addr_t)(p), .io_len = (len), \ } #define MSG_HANDLE(mode, value) \ { \ - .hnd_mode = (mode), \ - .hnd_value = (value), \ + .hnd_mode = (mode), .hnd_value = (value), \ } #define MSG(data, data_count, handles, handles_len) \ { \ - .msg_data = (data), \ - .msg_data_count = (data_count), \ - .msg_handles = (handles), \ - .msg_handles_count = (handles_len), \ + .msg_data = (data), .msg_data_count = (data_count), \ + .msg_handles = (handles), .msg_handles_count = (handles_len), \ } typedef uintptr_t phys_addr_t; @@ -75,6 +71,7 @@ typedef uint32_t kern_handle_t; typedef uint32_t kern_config_key_t; typedef uint32_t vm_prot_t; typedef int64_t ssize_t; +typedef uint32_t kern_futex_t; typedef unsigned short equeue_packet_type_t;