|  | // Copyright Microsoft and CHERIoT Contributors. | 
|  | // SPDX-License-Identifier: MIT | 
|  |  | 
|  | #include "hello.h" | 
|  | #include <debug.hh> | 
|  | #include <fail-simulator-on-error.h> | 
|  | #include <futex.h> | 
|  | #include <string_view> | 
|  |  | 
|  | /// Expose debugging features unconditionally for this compartment. | 
|  | using Debug = ConditionalDebug<true, "UART compartment">; | 
|  |  | 
|  | // Import some useful things from the CHERI namespace. | 
|  | using namespace CHERI; | 
|  |  | 
|  | /// Write a message to the UART. | 
|  | void write(const char *msg) | 
|  | { | 
|  | // Word containing the lock, this is 0 for unlocked, 1 for locked. | 
|  | static uint32_t lockWord = 0; | 
|  | with_interrupts_disabled([]() { | 
|  | // Check the word is 0, if it isn't then yield.  We may be woken after | 
|  | // another thread that manages to get the lock and so we need to retry | 
|  | // in a loop. | 
|  | while (lockWord != 0) | 
|  | { | 
|  | futex_wait(&lockWord, 0); | 
|  | } | 
|  | lockWord = 1; | 
|  | }); | 
|  | // Make sure that this is a valid readable capability. | 
|  | if (check_pointer<PermissionSet{Permission::Load}>(msg)) | 
|  | { | 
|  | // Don't assume that there's a null terminator. | 
|  | std::string_view message{msg, | 
|  | static_cast<size_t>(Capability{msg}.bounds())}; | 
|  | Debug::log("{}", message); | 
|  | } | 
|  | // Release the lock. | 
|  | lockWord = 0; | 
|  | futex_wake(&lockWord, -1); | 
|  | } |