blob: 025829c264cd7c1f598d5aa75080dae802d18d97 [file] [log] [blame]
// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT
#include "atomic.hh"
#include "string.h"
/**
* The variable-sized libcalls have the same names as builtins and clang
* doesn't let us define functions with the same name as builtins, so we define
* them without the `__` prefix and expose their assembly symbol as the expected
* name.
*/
#define DECLARE_ATOMIC_LIBCALL_ALIAS(name, ret, ...) \
[[cheri::interrupt_state(disabled)]] __cheri_libcall ret name( \
__VA_ARGS__) asm("__" #name);
/**
* Atomically load a variable number of bytes from `src` and store them in
* `dest`.
*/
DECLARE_ATOMIC_LIBCALL_ALIAS(atomic_load, void, int, const void *, void *, int)
void atomic_load(int size, const void *src, void *dest, int)
{
memcpy(dest, src, size);
}
/**
* Atomically load a variable number of bytes from `src` and store them in
* `dest`.
*/
DECLARE_ATOMIC_LIBCALL_ALIAS(atomic_store, void, int, void *, const void *, int)
void atomic_store(int size, void *dest, const void *src, int)
{
memcpy(dest, src, size);
}
/**
* Atomically replace the value at `ptr` with the value at `val` and the return
* the old value via `old`. All pointers point to at least `size` bytes.
*/
DECLARE_ATOMIC_LIBCALL_ALIAS(atomic_exchange,
void,
int,
void *,
void *,
const void *,
int)
void atomic_exchange(int size, void *ptr, void *old, const void *val, int)
{
memcpy(old, ptr, size);
memcpy(ptr, val, size);
}
/**
* Attempt to atomically replace `size` bytes pointed to by `ptr` with those at
* `desired`, if and only if they currently contain the same pattern pointed to
* by `expected`. Returns 1 on success, 0 on failure. In case of failure, the
* current object stored at `ptr` will be copied over `expected`.
*/
DECLARE_ATOMIC_LIBCALL_ALIAS(atomic_compare_exchange,
int,
int,
void *,
void *,
const void *,
int,
int)
int atomic_compare_exchange(int size,
void *ptr,
void *expected,
const void *desired,
int,
int)
{
if (memcmp(ptr, expected, size) == 0)
{
memcpy(ptr, desired, size);
return 1;
}
memcpy(expected, ptr, size);
return 0;
}