2025-09-10 05:32:19 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2025 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
#include <atomic>
|
2025-09-10 05:32:19 +00:00
|
|
|
#include <cstddef>
|
|
|
|
|
#include <cstdint>
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
#include <deque>
|
2025-10-31 10:59:39 +00:00
|
|
|
#include <functional>
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
#include <mutex>
|
|
|
|
|
#include <unordered_map>
|
2025-09-10 05:32:19 +00:00
|
|
|
|
|
|
|
|
namespace NEO {
|
|
|
|
|
|
|
|
|
|
class LinearStream;
|
2025-10-31 10:59:39 +00:00
|
|
|
class CommandStreamReceiver;
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
class IHostFunction;
|
2025-10-31 10:59:39 +00:00
|
|
|
class GraphicsAllocation;
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
struct RootDeviceEnvironment;
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
struct HostFunction {
|
|
|
|
|
uint64_t hostFunctionAddress = 0;
|
|
|
|
|
uint64_t userDataAddress = 0;
|
|
|
|
|
bool isInOrder = true;
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
void invoke() const {
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
using CallbackT = void (*)(void *);
|
|
|
|
|
CallbackT callback = reinterpret_cast<CallbackT>(hostFunctionAddress);
|
|
|
|
|
void *callbackData = reinterpret_cast<void *>(userDataAddress);
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
callback(callbackData);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
namespace HostFunctionStatus {
|
|
|
|
|
inline constexpr uint64_t completed = 0;
|
|
|
|
|
} // namespace HostFunctionStatus
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
namespace HostFunctionThreadPoolHelper {
|
|
|
|
|
inline constexpr int32_t unlimitedThreads = -1; // each CSR that uses host function creates worker thread in thread pool
|
|
|
|
|
}
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
class HostFunctionStreamer {
|
|
|
|
|
public:
|
|
|
|
|
HostFunctionStreamer(GraphicsAllocation *allocation, void *hostFunctionIdAddress, const std::function<void(GraphicsAllocation &)> &downloadAllocationImpl, bool isTbx);
|
|
|
|
|
~HostFunctionStreamer() = default;
|
|
|
|
|
|
|
|
|
|
uint64_t isHostFunctionReadyToExecute() const;
|
|
|
|
|
GraphicsAllocation *getHostFunctionIdAllocation() const;
|
|
|
|
|
HostFunction getHostFunction();
|
|
|
|
|
HostFunction getHostFunction(uint64_t hostFunctionId);
|
|
|
|
|
uint64_t getHostFunctionId() const;
|
|
|
|
|
uint64_t getHostFunctionIdGpuAddress() const;
|
|
|
|
|
volatile uint64_t *getHostFunctionIdPtr() const;
|
|
|
|
|
uint64_t getNextHostFunctionIdAndIncrement();
|
|
|
|
|
|
|
|
|
|
void addHostFunction(uint64_t hostFunctionId, HostFunction &&hostFunction);
|
|
|
|
|
void downloadHostFunctionAllocation() const;
|
|
|
|
|
void signalHostFunctionCompletion(const HostFunction &hostFunction);
|
|
|
|
|
void prepareForExecution(const HostFunction &hostFunction);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::mutex hostFunctionsMutex;
|
|
|
|
|
std::unordered_map<uint64_t, HostFunction> hostFunctions;
|
|
|
|
|
volatile uint64_t *hostFunctionIdAddress = nullptr; // 0 bit - used to signal that host function is pending or completed
|
|
|
|
|
GraphicsAllocation *allocation = nullptr;
|
|
|
|
|
std::function<void(GraphicsAllocation &)> downloadAllocationImpl;
|
|
|
|
|
std::atomic<uint64_t> nextHostFunctionId{1};
|
|
|
|
|
std::atomic<uint32_t> pendingHostFunctions{0};
|
|
|
|
|
std::atomic<bool> isBusy{false};
|
|
|
|
|
const bool isTbx = false;
|
|
|
|
|
};
|
2025-09-10 05:32:19 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
enum class HostFunctionWorkerMode : int32_t {
|
|
|
|
|
defaultMode = -1,
|
|
|
|
|
countingSemaphore = 0,
|
|
|
|
|
schedulerWithThreadPool = 1,
|
|
|
|
|
};
|
2025-09-22 11:19:51 +00:00
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
template <typename GfxFamily>
|
|
|
|
|
struct HostFunctionHelper {
|
|
|
|
|
static void programHostFunction(LinearStream &commandStream, HostFunctionStreamer &streamer, HostFunction &&hostFunction);
|
|
|
|
|
static void programHostFunctionId(LinearStream *commandStream, void *cmdBuffer, HostFunctionStreamer &streamer, HostFunction &&hostFunction);
|
|
|
|
|
static void programHostFunctionWaitForCompletion(LinearStream *commandStream, void *cmdBuffer, const HostFunctionStreamer &streamer);
|
2025-09-10 05:32:19 +00:00
|
|
|
};
|
|
|
|
|
|
2025-10-31 10:59:39 +00:00
|
|
|
namespace HostFunctionFactory {
|
|
|
|
|
|
feature: redesign host function workers
Each host function gets its unique ID within a CSR,
uses 1 mi store to write ID - to signal that host function is ready,
and 1 mi semaphore wait will wait for the ID to be cleared,
Use 0th bit from ID as pending/completed flag,
host function ID is incremented by 2, and starts with 1.
So each ID will always have 0bit set.
This is a must have since semaphore wait can wait for 4 bytes only.
Adjust command buffer programming and patching logic to IDs.
Add hostFunction callable class - using invoke method,
which stores required information about callback.
Add host function streamer - stores all host function data
for a given CSR.
All user provided host functions are stored in unordered map,
where key is host function ID.
Add host function scheduler, and a thread pool - under debug flag
Single threaded scheduler loops over all registered host function streamers,
dispatch ready to execute host functions to thread pool.
Allow for out of order host functions execution for OOQ - under debug flag,
each host function has bool isInOrder flag which indicates if it can be
executed Out Of Order - in this mode, ID tag will be cleared immediately,
so semaphore wait will unblock before the host function execution.
Remove Host Function worker CV and atomics based implementation.
Rename classes
Related-To: NEO-14577
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
2025-11-24 20:35:14 +00:00
|
|
|
void createAndSetHostFunctionWorker(HostFunctionWorkerMode hostFunctionWorkerMode,
|
|
|
|
|
bool skipHostFunctionExecution,
|
|
|
|
|
CommandStreamReceiver *csr,
|
|
|
|
|
RootDeviceEnvironment *rootDeviceEnvironment);
|
|
|
|
|
|
|
|
|
|
} // namespace HostFunctionFactory
|
2025-10-31 10:59:39 +00:00
|
|
|
|
2025-09-10 05:32:19 +00:00
|
|
|
} // namespace NEO
|