Make UEFI boot-platform build again
[haiku.git] / headers / private / kernel / arch / generic / user_memory.h
blob6d18fed1c31cbff4bcd246b490df85b05b7a8677
1 /*
2 * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef _KERNEL_ARCH_GENERIC_USER_MEMORY_H
6 #define _KERNEL_ARCH_GENERIC_USER_MEMORY_H
9 #include <atomic>
11 #include <setjmp.h>
12 #include <string.h>
14 #include <thread.h>
17 namespace {
20 struct FaultHandlerGuard {
21 FaultHandlerGuard()
23 ASSERT(thread_get_current_thread()->fault_handler == nullptr);
24 thread_get_current_thread()->fault_handler = HandleFault;
25 std::atomic_signal_fence(std::memory_order_acq_rel);
29 ~FaultHandlerGuard()
31 std::atomic_signal_fence(std::memory_order_acq_rel);
32 thread_get_current_thread()->fault_handler = nullptr;
36 [[noreturn]] static void HandleFault()
38 longjmp(thread_get_current_thread()->fault_handler_state, 1);
43 template<typename Function>
44 bool user_access(Function function)
46 FaultHandlerGuard guard;
47 // TODO: try { } catch (...) { } would be much nicer, wouldn't it?
48 // And faster... And world wouldn't end in a terrible disaster if function()
49 // or anything it calls created on stack an object with non-trivial
50 // destructor.
51 auto fail = setjmp(thread_get_current_thread()->fault_handler_state);
52 if (fail == 0) {
53 function();
54 return true;
56 return false;
60 inline status_t
61 arch_cpu_user_memcpy(void* src, const void* dst, size_t n)
63 return user_access([=] { memcpy(src, dst, n); }) ? B_OK : B_ERROR;
67 inline status_t
68 arch_cpu_user_memset(void* src, char v, size_t n)
70 return user_access([=] { memset(src, v, n); }) ? B_OK : B_ERROR;
74 inline ssize_t
75 arch_cpu_user_strlcpy(char* src, const char* dst, size_t n)
77 ssize_t result;
78 return user_access([=, &result] { result = strlcpy(src, dst, n); })
79 ? result : B_ERROR;
84 #endif // _KERNEL_ARCH_GENERIC_USER_MEMORY_H