This repository has been archived by the owner on Sep 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fast userspace mutex (behaves like a semaphore) which only requires a syscall in the case of contention.
- Loading branch information
Showing
11 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
#include "types.h" | ||
|
||
#define FUTEX_INIT 1 | ||
#define FUTEX_DESTROY 2 | ||
#define FUTEX_WAIT 3 | ||
|
||
__DECL_BEGIN | ||
|
||
typedef int futex_t; | ||
|
||
__DECL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#include "../tasking/Process.h" | ||
#include "../kernel/api/futex.h" | ||
#include "../kernel/memory/SafePointer.h" | ||
|
||
int Process::sys_futex(UserspacePointer<futex_t> futex, int op) { | ||
auto addr = (uintptr_t) futex.raw(); | ||
if (addr > HIGHER_HALF) | ||
return -EFAULT; | ||
auto reg_res = _vm_space->get_region_containing(addr); | ||
if (reg_res.is_error()) | ||
return -EFAULT; | ||
auto reg = reg_res.value(); | ||
if (!reg->prot().read || !reg->prot().write) | ||
return -EPERM; | ||
|
||
switch (op) { | ||
case FUTEX_INIT: { | ||
LOCK(m_futex_lock); | ||
if (m_futexes.contains(addr)) | ||
return -EEXIST; | ||
m_futexes[addr] = kstd::Arc(new Futex(reg->object(), addr - reg->start())); | ||
return SUCCESS; | ||
} | ||
case FUTEX_DESTROY: { | ||
LOCK(m_futex_lock); | ||
if (!m_futexes.contains(addr)) | ||
return -ENOENT; | ||
m_futexes.erase(addr); | ||
} | ||
case FUTEX_WAIT: { | ||
auto k_futex = m_futex_lock.synced<kstd::Arc<Futex>>([this, addr]() { | ||
auto node = m_futexes.find_node(addr); | ||
if (!node) | ||
return kstd::Arc<Futex>(); | ||
return node->data.second; | ||
}); | ||
if (!k_futex) | ||
return -ENOENT; | ||
TaskManager::current_thread()->block(*k_futex); | ||
return SUCCESS; | ||
} | ||
default: | ||
return -EINVAL; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#include "Futex.h" | ||
#include "../memory/MemoryManager.h" | ||
|
||
Futex::Futex(kstd::Arc<VMObject> object, size_t offset_in_object): | ||
m_object(kstd::move(object)), | ||
m_k_region(MM.map_object(m_object)), | ||
m_var((Atomic<int>*) (m_k_region->start() + offset_in_object)) | ||
{ | ||
ASSERT(offset_in_object + sizeof(*m_var) <= m_object->size()); | ||
} | ||
|
||
bool Futex::is_ready() { | ||
return m_var->load(MemoryOrder::Relaxed) > 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "Blocker.h" | ||
#include "../memory/VMRegion.h" | ||
|
||
class Futex: public Blocker { | ||
public: | ||
Futex(kstd::Arc<VMObject> object, size_t offset_in_object); | ||
|
||
bool is_ready() override; | ||
|
||
private: | ||
kstd::Arc<VMObject> m_object; | ||
kstd::Arc<VMRegion> m_k_region; | ||
Atomic<int>* m_var; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ SET(SOURCES | |
strings.c | ||
sys/ioctl.c | ||
sys/shm.c | ||
sys/futex.c | ||
sys/printf.c | ||
sys/ptrace.c | ||
sys/liballoc.cpp | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#include "futex.h" | ||
#include "syscall.h" | ||
|
||
int futex_init(futex_t* futex, int val) { | ||
*futex = val; | ||
return syscall3(SYS_FUTEX, (int) futex, FUTEX_INIT); | ||
} | ||
|
||
int futex_destroy(futex_t* futex) { | ||
return syscall3(SYS_FUTEX, (int) futex, FUTEX_DESTROY); | ||
} | ||
|
||
void futex_wait(futex_t* futex) { | ||
int exp = __atomic_load_n(futex, __ATOMIC_RELAXED); | ||
while (1) { | ||
if (exp > 0) { | ||
if (__atomic_compare_exchange_n(futex, &exp, exp - 1, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) | ||
break; | ||
} else { | ||
if (syscall3_noerr(SYS_FUTEX, (int) futex, FUTEX_WAIT)) | ||
return; | ||
exp = __atomic_load_n(futex, __ATOMIC_RELAXED); | ||
} | ||
} | ||
} | ||
|
||
void futex_signal(futex_t* futex) { | ||
__atomic_fetch_add(futex, 1, __ATOMIC_ACQUIRE); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
#include <kernel/api/futex.h> | ||
|
||
__DECL_BEGIN | ||
|
||
/** | ||
* Initializes a futex. | ||
* @param futex Pointer to the futex_t to initialize. | ||
* @param val The value to initialize the futex with. | ||
* @return 0 on success, -1 on error (errno set). | ||
*/ | ||
int futex_init(futex_t* futex, int val); | ||
|
||
/** | ||
* Destroys a futex. | ||
* @param futex Pointer to the futex to destroy. | ||
* @return 0 on success, -1 on error (errno set). | ||
*/ | ||
int futex_destroy(futex_t* futex); | ||
|
||
/** | ||
* Waits for a futex to be greater than zero and then subtracts one from its stored value. | ||
* @param futex Pointer to the futex to wait on. | ||
*/ | ||
void futex_wait(futex_t* futex); | ||
|
||
/** | ||
* Adds one to the futex's stored value. | ||
* @param futex Poitner to the futex to signal. | ||
*/ | ||
void futex_signal(futex_t* futex); | ||
|
||
__DECL_END |