mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Replace Remaining Types
Somehow a few size_t slipped through https://github.com/official-stockfish/Stockfish/pull/6874 closes https://github.com/official-stockfish/Stockfish/pull/6897 No functional change
This commit is contained in:
+2
-1
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "benchmark.h"
|
#include "benchmark.h"
|
||||||
#include "numa.h"
|
#include "numa.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -483,7 +484,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) {
|
|||||||
|
|
||||||
float totalTime = 0;
|
float totalTime = 0;
|
||||||
for (const auto& game : BenchmarkPositions)
|
for (const auto& game : BenchmarkPositions)
|
||||||
for (size_t i = 0; i < game.size(); ++i)
|
for (usize i = 0; i < game.size(); ++i)
|
||||||
totalTime += float(getCorrectedTime(i + 1));
|
totalTime += float(getCorrectedTime(i + 1));
|
||||||
|
|
||||||
float timeScaleFactor = static_cast<float>(desiredTimeS * 1000) / totalTime;
|
float timeScaleFactor = static_cast<float>(desiredTimeS * 1000) / totalTime;
|
||||||
|
|||||||
+14
-14
@@ -68,7 +68,7 @@ namespace Stockfish {
|
|||||||
// availability of aligned_alloc(). Memory allocated with std_aligned_alloc()
|
// availability of aligned_alloc(). Memory allocated with std_aligned_alloc()
|
||||||
// must be freed with std_aligned_free().
|
// must be freed with std_aligned_free().
|
||||||
|
|
||||||
void* std_aligned_alloc(size_t alignment, size_t size) {
|
void* std_aligned_alloc(usize alignment, usize size) {
|
||||||
#if defined(_ISOC11_SOURCE)
|
#if defined(_ISOC11_SOURCE)
|
||||||
return aligned_alloc(alignment, size);
|
return aligned_alloc(alignment, size);
|
||||||
#elif defined(POSIXALIGNEDALLOC)
|
#elif defined(POSIXALIGNEDALLOC)
|
||||||
@@ -102,19 +102,19 @@ void std_aligned_free(void* ptr) {
|
|||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize) {
|
static void* aligned_large_pages_alloc_windows([[maybe_unused]] usize allocSize) {
|
||||||
|
|
||||||
return windows_try_with_large_page_priviliges(
|
return windows_try_with_large_page_priviliges(
|
||||||
[&](size_t largePageSize) {
|
[&](usize largePageSize) {
|
||||||
// Round up size to full pages and allocate
|
// Round up size to full pages and allocate
|
||||||
allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
|
allocSize = (allocSize + largePageSize - 1) & ~usize(largePageSize - 1);
|
||||||
return VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
|
return VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
},
|
},
|
||||||
[]() { return (void*) nullptr; });
|
[]() { return (void*) nullptr; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void* aligned_large_pages_alloc_with_hint(size_t allocSize, bool) {
|
void* aligned_large_pages_alloc_with_hint(usize allocSize, bool) {
|
||||||
|
|
||||||
// Try to allocate large pages
|
// Try to allocate large pages
|
||||||
void* mem = aligned_large_pages_alloc_windows(allocSize);
|
void* mem = aligned_large_pages_alloc_windows(allocSize);
|
||||||
@@ -131,11 +131,11 @@ void* aligned_large_pages_alloc_with_hint(size_t allocSize, bool) {
|
|||||||
#if defined(__linux__) && defined(MAP_HUGE_SHIFT) && defined(__x86_64__)
|
#if defined(__linux__) && defined(MAP_HUGE_SHIFT) && defined(__x86_64__)
|
||||||
#define HAS_HUGE_PAGES
|
#define HAS_HUGE_PAGES
|
||||||
|
|
||||||
static std::map<void*, size_t> huge_pages;
|
static std::map<void*, usize> huge_pages;
|
||||||
static std::mutex huge_pages_mtx;
|
static std::mutex huge_pages_mtx;
|
||||||
|
|
||||||
static void* try_huge_pages_alloc(size_t allocSize) {
|
static void* try_huge_pages_alloc(usize allocSize) {
|
||||||
size_t size = ((allocSize + HugePageSize - 1) / HugePageSize) * HugePageSize;
|
usize size = ((allocSize + HugePageSize - 1) / HugePageSize) * HugePageSize;
|
||||||
void* mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
void* mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | (30 << MAP_HUGE_SHIFT), -1, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | (30 << MAP_HUGE_SHIFT), -1, 0);
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ static void* try_huge_pages_alloc(size_t allocSize) {
|
|||||||
}
|
}
|
||||||
#endif // defined(__linux__) && defined(MAP_HUGE_SHIFT) && defined(__x86_64__)
|
#endif // defined(__linux__) && defined(MAP_HUGE_SHIFT) && defined(__x86_64__)
|
||||||
|
|
||||||
void* aligned_large_pages_alloc_with_hint(size_t allocSize, [[maybe_unused]] bool hugePageHint) {
|
void* aligned_large_pages_alloc_with_hint(usize allocSize, [[maybe_unused]] bool hugePageHint) {
|
||||||
#ifdef HAS_HUGE_PAGES
|
#ifdef HAS_HUGE_PAGES
|
||||||
if (hugePageHint && allocSize >= HugePageSize)
|
if (hugePageHint && allocSize >= HugePageSize)
|
||||||
{
|
{
|
||||||
@@ -159,13 +159,13 @@ void* aligned_large_pages_alloc_with_hint(size_t allocSize, [[maybe_unused]] boo
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
constexpr size_t alignment = 2 * 1024 * 1024; // 2MB page size assumed
|
constexpr usize alignment = 2 * 1024 * 1024; // 2MB page size assumed
|
||||||
#else
|
#else
|
||||||
constexpr size_t alignment = 4096; // small page size assumed
|
constexpr usize alignment = 4096; // small page size assumed
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Round up to multiples of alignment
|
// Round up to multiples of alignment
|
||||||
size_t size = ((allocSize + alignment - 1) / alignment) * alignment;
|
usize size = ((allocSize + alignment - 1) / alignment) * alignment;
|
||||||
void* mem = std_aligned_alloc(alignment, size);
|
void* mem = std_aligned_alloc(alignment, size);
|
||||||
#if defined(MADV_HUGEPAGE)
|
#if defined(MADV_HUGEPAGE)
|
||||||
madvise(mem, size, MADV_HUGEPAGE);
|
madvise(mem, size, MADV_HUGEPAGE);
|
||||||
@@ -175,7 +175,7 @@ void* aligned_large_pages_alloc_with_hint(size_t allocSize, [[maybe_unused]] boo
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void* aligned_large_pages_alloc(size_t size) {
|
void* aligned_large_pages_alloc(usize size) {
|
||||||
return aligned_large_pages_alloc_with_hint(size, false);
|
return aligned_large_pages_alloc_with_hint(size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ bool has_large_pages() {
|
|||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
constexpr size_t page_size = 2 * 1024 * 1024; // 2MB page size assumed
|
constexpr usize page_size = 2 * 1024 * 1024; // 2MB page size assumed
|
||||||
void* mem = aligned_large_pages_alloc_windows(page_size);
|
void* mem = aligned_large_pages_alloc_windows(page_size);
|
||||||
if (mem == nullptr)
|
if (mem == nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
+17
-16
@@ -28,6 +28,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
|
|
||||||
@@ -61,14 +62,14 @@ using AdjustTokenPrivileges_t =
|
|||||||
|
|
||||||
namespace Stockfish {
|
namespace Stockfish {
|
||||||
|
|
||||||
constexpr size_t HugePageSize = size_t(1) << 30;
|
constexpr usize HugePageSize = usize(1) << 30;
|
||||||
|
|
||||||
void* std_aligned_alloc(size_t alignment, size_t size);
|
void* std_aligned_alloc(usize alignment, usize size);
|
||||||
void std_aligned_free(void* ptr);
|
void std_aligned_free(void* ptr);
|
||||||
|
|
||||||
// Memory aligned by page size, min alignment: 4096 bytes
|
// Memory aligned by page size, min alignment: 4096 bytes
|
||||||
void* aligned_large_pages_alloc_with_hint(size_t size, bool hugePageHint);
|
void* aligned_large_pages_alloc_with_hint(usize size, bool hugePageHint);
|
||||||
void* aligned_large_pages_alloc(size_t size);
|
void* aligned_large_pages_alloc(usize size);
|
||||||
void aligned_large_pages_free(void* mem);
|
void aligned_large_pages_free(void* mem);
|
||||||
|
|
||||||
bool has_large_pages();
|
bool has_large_pages();
|
||||||
@@ -96,15 +97,15 @@ void memory_deleter_array(T* ptr, FREE_FUNC free_func) {
|
|||||||
|
|
||||||
|
|
||||||
// Move back on the pointer to where the size is allocated
|
// Move back on the pointer to where the size is allocated
|
||||||
const size_t array_offset = std::max(sizeof(size_t), alignof(T));
|
const usize array_offset = std::max(sizeof(usize), alignof(T));
|
||||||
char* raw_memory = reinterpret_cast<char*>(ptr) - array_offset;
|
char* raw_memory = reinterpret_cast<char*>(ptr) - array_offset;
|
||||||
|
|
||||||
if constexpr (!std::is_trivially_destructible_v<T>)
|
if constexpr (!std::is_trivially_destructible_v<T>)
|
||||||
{
|
{
|
||||||
const size_t size = *reinterpret_cast<size_t*>(raw_memory);
|
const usize size = *reinterpret_cast<usize*>(raw_memory);
|
||||||
|
|
||||||
// Explicitly call the destructor for each element in reverse order
|
// Explicitly call the destructor for each element in reverse order
|
||||||
for (size_t i = size; i-- > 0;)
|
for (usize i = size; i-- > 0;)
|
||||||
ptr[i].~T();
|
ptr[i].~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,19 +124,19 @@ inline std::enable_if_t<!std::is_array_v<T>, T*> memory_allocator(ALLOC_FUNC all
|
|||||||
// Allocates memory for an array of unknown bound and places it there with placement new
|
// Allocates memory for an array of unknown bound and places it there with placement new
|
||||||
template<typename T, typename ALLOC_FUNC>
|
template<typename T, typename ALLOC_FUNC>
|
||||||
inline std::enable_if_t<std::is_array_v<T>, std::remove_extent_t<T>*>
|
inline std::enable_if_t<std::is_array_v<T>, std::remove_extent_t<T>*>
|
||||||
memory_allocator(ALLOC_FUNC alloc_func, size_t num) {
|
memory_allocator(ALLOC_FUNC alloc_func, usize num) {
|
||||||
using ElementType = std::remove_extent_t<T>;
|
using ElementType = std::remove_extent_t<T>;
|
||||||
|
|
||||||
const size_t array_offset = std::max(sizeof(size_t), alignof(ElementType));
|
const usize array_offset = std::max(sizeof(usize), alignof(ElementType));
|
||||||
|
|
||||||
// Save the array size in the memory location
|
// Save the array size in the memory location
|
||||||
char* raw_memory =
|
char* raw_memory =
|
||||||
reinterpret_cast<char*>(alloc_func(array_offset + num * sizeof(ElementType)));
|
reinterpret_cast<char*>(alloc_func(array_offset + num * sizeof(ElementType)));
|
||||||
ASSERT_ALIGNED(raw_memory, alignof(T));
|
ASSERT_ALIGNED(raw_memory, alignof(T));
|
||||||
|
|
||||||
new (raw_memory) size_t(num);
|
new (raw_memory) usize(num);
|
||||||
|
|
||||||
for (size_t i = 0; i < num; ++i)
|
for (usize i = 0; i < num; ++i)
|
||||||
new (raw_memory + array_offset + i * sizeof(ElementType)) ElementType();
|
new (raw_memory + array_offset + i * sizeof(ElementType)) ElementType();
|
||||||
|
|
||||||
// Need to return the pointer at the start of the array so that
|
// Need to return the pointer at the start of the array so that
|
||||||
@@ -178,7 +179,7 @@ std::enable_if_t<!std::is_array_v<T>, LargePagePtr<T>> make_unique_large_page(Ar
|
|||||||
|
|
||||||
// make_unique_large_page for arrays of unknown bound
|
// make_unique_large_page for arrays of unknown bound
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_array_v<T>, LargePagePtr<T>> make_unique_large_page(size_t num) {
|
std::enable_if_t<std::is_array_v<T>, LargePagePtr<T>> make_unique_large_page(usize num) {
|
||||||
using ElementType = std::remove_extent_t<T>;
|
using ElementType = std::remove_extent_t<T>;
|
||||||
|
|
||||||
static_assert(alignof(ElementType) <= 4096,
|
static_assert(alignof(ElementType) <= 4096,
|
||||||
@@ -214,7 +215,7 @@ using AlignedPtr =
|
|||||||
// make_unique_aligned for single objects
|
// make_unique_aligned for single objects
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
std::enable_if_t<!std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(Args&&... args) {
|
std::enable_if_t<!std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(Args&&... args) {
|
||||||
const auto func = [](size_t size) { return std_aligned_alloc(alignof(T), size); };
|
const auto func = [](usize size) { return std_aligned_alloc(alignof(T), size); };
|
||||||
T* obj = memory_allocator<T>(func, std::forward<Args>(args)...);
|
T* obj = memory_allocator<T>(func, std::forward<Args>(args)...);
|
||||||
|
|
||||||
return AlignedPtr<T>(obj);
|
return AlignedPtr<T>(obj);
|
||||||
@@ -222,10 +223,10 @@ std::enable_if_t<!std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(Args&&.
|
|||||||
|
|
||||||
// make_unique_aligned for arrays of unknown bound
|
// make_unique_aligned for arrays of unknown bound
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(size_t num) {
|
std::enable_if_t<std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(usize num) {
|
||||||
using ElementType = std::remove_extent_t<T>;
|
using ElementType = std::remove_extent_t<T>;
|
||||||
|
|
||||||
const auto func = [](size_t size) { return std_aligned_alloc(alignof(ElementType), size); };
|
const auto func = [](usize size) { return std_aligned_alloc(alignof(ElementType), size); };
|
||||||
ElementType* memory = memory_allocator<T>(func, num);
|
ElementType* memory = memory_allocator<T>(func, num);
|
||||||
|
|
||||||
return AlignedPtr<T>(memory);
|
return AlignedPtr<T>(memory);
|
||||||
@@ -256,7 +257,7 @@ auto windows_try_with_large_page_priviliges([[maybe_unused]] FuncYesT&& fyes, Fu
|
|||||||
HANDLE hProcessToken{};
|
HANDLE hProcessToken{};
|
||||||
LUID luid{};
|
LUID luid{};
|
||||||
|
|
||||||
const size_t largePageSize = GetLargePageMinimum();
|
const usize largePageSize = GetLargePageMinimum();
|
||||||
if (!largePageSize)
|
if (!largePageSize)
|
||||||
return fno();
|
return fno();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -349,7 +349,7 @@ template<typename T>
|
|||||||
class RelaxedAtomic {
|
class RelaxedAtomic {
|
||||||
static constexpr bool UseAtomic =
|
static constexpr bool UseAtomic =
|
||||||
#ifdef USE_SLOPPY_ATOMICS
|
#ifdef USE_SLOPPY_ATOMICS
|
||||||
!std::atomic<T>::is_always_lock_free || sizeof(T) > sizeof(size_t);
|
!std::atomic<T>::is_always_lock_free || sizeof(T) > sizeof(usize);
|
||||||
#else
|
#else
|
||||||
true;
|
true;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-2
@@ -20,8 +20,8 @@
|
|||||||
#define MOVEGEN_H_INCLUDED
|
#define MOVEGEN_H_INCLUDED
|
||||||
|
|
||||||
#include <algorithm> // IWYU pragma: keep
|
#include <algorithm> // IWYU pragma: keep
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace Stockfish {
|
namespace Stockfish {
|
||||||
@@ -61,7 +61,7 @@ struct MoveList {
|
|||||||
last(generate<T>(pos, moveList)) {}
|
last(generate<T>(pos, moveList)) {}
|
||||||
const Move* begin() const { return moveList; }
|
const Move* begin() const { return moveList; }
|
||||||
const Move* end() const { return last; }
|
const Move* end() const { return last; }
|
||||||
size_t size() const { return last - moveList; }
|
usize size() const { return last - moveList; }
|
||||||
bool contains(Move move) const { return std::find(begin(), end(), move) != end(); }
|
bool contains(Move move) const { return std::find(begin(), end(), move) != end(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
namespace Stockfish::Eval::NNUE {
|
namespace Stockfish::Eval::NNUE {
|
||||||
|
|
||||||
template<size_t Dimensions>
|
template<usize Dimensions>
|
||||||
struct NNZInfo {
|
struct NNZInfo {
|
||||||
|
|
||||||
#if defined(USE_AVX512)
|
#if defined(USE_AVX512)
|
||||||
@@ -146,7 +146,7 @@ struct NNZInfo {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t bytes = sizeof(neurons1) / 32;
|
usize bytes = sizeof(neurons1) / 32;
|
||||||
memcpy(out, &m1, bytes);
|
memcpy(out, &m1, bytes);
|
||||||
out += bytes;
|
out += bytes;
|
||||||
memcpy(out, &m2, bytes);
|
memcpy(out, &m2, bytes);
|
||||||
|
|||||||
+1
-2
@@ -171,8 +171,7 @@ inline __m128i _mm_cvtsi64_si128(i64 val) {
|
|||||||
#ifdef __wasm__
|
#ifdef __wasm__
|
||||||
#define vec_convert_8_16(a) wasm_i16x8_load8x8(reinterpret_cast<const void*>(&a))
|
#define vec_convert_8_16(a) wasm_i16x8_load8x8(reinterpret_cast<const void*>(&a))
|
||||||
#else
|
#else
|
||||||
#define vec_convert_8_16(a) \
|
#define vec_convert_8_16(a) _mm_cvtepi8_epi16(_mm_cvtsi64_si128(static_cast<i64>(a)))
|
||||||
_mm_cvtepi8_epi16(_mm_cvtsi64_si128(static_cast<int64_t>(a)))
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
// Credit: Yoshie2000
|
// Credit: Yoshie2000
|
||||||
|
|||||||
+1
-1
@@ -375,7 +375,7 @@ class Worker {
|
|||||||
|
|
||||||
LimitsType limits;
|
LimitsType limits;
|
||||||
|
|
||||||
size_t pvIdx, pvLast;
|
usize pvIdx, pvLast;
|
||||||
RelaxedAtomic<u64> nodes, tbHits, bestMoveChanges;
|
RelaxedAtomic<u64> nodes, tbHits, bestMoveChanges;
|
||||||
int selDepth, nmpMinPly;
|
int selDepth, nmpMinPly;
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Stockfish {
|
|||||||
class NativeThread {
|
class NativeThread {
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
|
||||||
static constexpr size_t TH_STACK_SIZE = 8 * 1024 * 1024;
|
static constexpr usize TH_STACK_SIZE = 8 * 1024 * 1024;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class Function, class... Args>
|
template<class Function, class... Args>
|
||||||
|
|||||||
+4
-3
@@ -19,13 +19,14 @@
|
|||||||
#ifndef TUNE_H_INCLUDED
|
#ifndef TUNE_H_INCLUDED
|
||||||
#define TUNE_H_INCLUDED
|
#define TUNE_H_INCLUDED
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits> // IWYU pragma: keep
|
#include <type_traits> // IWYU pragma: keep
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
namespace Stockfish {
|
namespace Stockfish {
|
||||||
|
|
||||||
class OptionsMap;
|
class OptionsMap;
|
||||||
@@ -132,9 +133,9 @@ class Tune {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Template specialization for arrays: recursively handle multi-dimensional arrays
|
// Template specialization for arrays: recursively handle multi-dimensional arrays
|
||||||
template<typename T, size_t N, typename... Args>
|
template<typename T, usize N, typename... Args>
|
||||||
int add(const SetRange& range, std::string&& names, T (&value)[N], Args&&... args) {
|
int add(const SetRange& range, std::string&& names, T (&value)[N], Args&&... args) {
|
||||||
for (size_t i = 0; i < N; i++)
|
for (usize i = 0; i < N; i++)
|
||||||
add(range, next(names, i == N - 1) + "[" + std::to_string(i) + "]", value[i]);
|
add(range, next(names, i == N - 1) + "[" + std::to_string(i) + "]", value[i]);
|
||||||
return add(range, std::move(names), args...);
|
return add(range, std::move(names), args...);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user