Files
salmanoff/include/user/senseApiDesc.h
T
hayodea cde2737876 Libspinscale: Initial top-level SMO port to coroutine framework
We haven't ported everything. Just the top-level methods. We'll
dig in to the leaf stuff later. Surprisingly, this all went without
any real difficulties.

Runs like a charm on first try.
2026-05-24 23:26:18 -04:00

242 lines
7.9 KiB
C++

#ifndef __USER_SENSE_API_LIB_H__
#define __USER_SENSE_API_LIB_H__
#include <stdbool.h>
#include <optional>
#include <string>
#include <functional>
#include <memory>
#include <vector>
#include <preprocessor.h>
#include <user/deviceAttachmentSpec.h>
#include <spinscale/cps/callback.h>
#include <spinscale/componentThread.h>
#define CL_TARGET_OPENCL_VERSION 120
#include <CL/cl.h>
class OptionParser;
namespace smo {
namespace compute {
class ClBuffer;
class ComputeDevice;
} // namespace compute
namespace stim_buff {
/**
* @brief Threading model descriptor for senseApi libraries.
*
* This structure provides senseApi libraries with access to the information and
* resources they need to operate with SMO's threading model.
*/
struct SmoThreadingModelDesc
{
/**
* @brief sh_ptr to ComponentThread for device-independent state mgt.
*
* This ComponentThread should be used by senseApis for state management
* that's independent of any particular device or attachment spec.
* SMO will usually pass in the Marionette thread here.
*
* State management that's tied to a particular attachment spec should be
* done on the ComponentThread for the thread that SMO provided in the
* attachDeviceReq call.
*/
std::shared_ptr<sscl::ComponentThread> componentThread;
};
typedef std::function<void(bool, std::shared_ptr<device::DeviceAttachmentSpec>)>
sal_mlo_attachDeviceReqCbFn;
typedef std::function<void(bool, std::shared_ptr<device::DeviceAttachmentSpec>)>
sal_mlo_detachDeviceReqCbFn;
typedef int (sal_mlo_initializeIndFn)(void);
typedef int (sal_mlo_finalizeIndFn)(void);
typedef void (sal_mlo_attachDeviceReqFn)(
const std::shared_ptr<device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<sscl::ComponentThread>& componentThread,
sscl::cps::Callback<sal_mlo_attachDeviceReqCbFn> cb);
typedef void (sal_mlo_detachDeviceReqFn)(
const std::shared_ptr<device::DeviceAttachmentSpec>& desc,
sscl::cps::Callback<sal_mlo_detachDeviceReqCbFn> cb);
/**
* @brief Hooks provided by Salmanoff to senseApi libraries.
* This structure contains function pointers that senseApi libraries can use
* to interact with Salmanoff's functionality, such as searching for commonLibs.
*/
struct SmoCallbacks
{
/**
* @brief Search for a library in Salmanoff's search paths
* @param libraryPath The relative filename of the library to search for
* @return Optional containing the full path if found, nullopt if not found
*
* This function searches for the given library in the same search paths
* that Salmanoff uses when loading senseApi libraries (user-specified
* paths via -p option, current directory, and executable directory).
*/
std::optional<std::string> (*searchForLibInSmoSearchPaths)(
const std::string& libraryPath);
/**
* @brief Get the current ComponentThread instance
* @return Shared pointer to the current ComponentThread
*
* This function provides access to the current ComponentThread instance,
* equivalent to calling sscl::ComponentThread::getSelf().
*/
std::shared_ptr<sscl::ComponentThread> (*ComponentThread_getSelf)(void);
/**
* @brief Get the OptionParser singleton instance
* @return Reference to the OptionParser singleton
*
* This function provides access to the OptionParser singleton instance,
* equivalent to calling OptionParser::getOptions().
*/
OptionParser& (*OptionParser_getOptions)(void);
/**
* @brief Create a USE_HOST_PTR buffer on all OpenCL contexts
* @param hostPtr Host pointer to the memory
* @param size Size of the buffer in bytes
* @param flags Additional OpenCL memory flags
* @return Shared pointer to ClBuffer managing buffers on all devices
*/
std::shared_ptr<smo::compute::ClBuffer>
(*ComputeManager_createUseHostPtrBuffer)(
void* hostPtr, size_t size, cl_mem_flags flags);
/**
* @brief Release USE_HOST_PTR buffers from all contexts
* @param buffer Shared pointer to ClBuffer to release
*/
void (*ComputeManager_releaseUseHostPtrBuffer)(
std::shared_ptr<smo::compute::ClBuffer> buffer);
/**
* @brief Get a compute device
* @return Shared pointer to ComputeDevice, or nullptr if no devices available
*/
std::shared_ptr<smo::compute::ComputeDevice>
(*ComputeManager_getDevice)(void);
/**
* @brief Release a compute device
* @param device Shared pointer to ComputeDevice to release
*/
void (*ComputeManager_releaseDevice)(
std::shared_ptr<smo::compute::ComputeDevice> device);
};
struct Sal_Mgmt_LibOps
{
/* When Salmanoff loads a stim buff API lib, it calls this function to initialize
* the lib. When this returns, the lib should be ready to attach devices.
*/
sal_mlo_initializeIndFn *initializeInd;
/* Salmanoff calls this to finalize the lib and free its internal
* resources. When this returns, the lib should be ready to be unloaded.
*/
sal_mlo_finalizeIndFn *finalizeInd;
/* Salmanoff calls this to attach a device to the lib. When it returns, the
* device should be attached and ready to present its stimbuff.
*/
sal_mlo_attachDeviceReqFn *attachDeviceReq;
// When this returns, the device should be detached.
sal_mlo_detachDeviceReqFn *detachDeviceReq;
static bool sanityCheck(const Sal_Mgmt_LibOps &ops)
{
if (!ops.initializeInd || !ops.finalizeInd
|| !ops.attachDeviceReq || !ops.detachDeviceReq)
{
return false;
}
return true;
}
};
/* Exported by all stim buff API Libraries to tell Salmanoff what API the lib uses
* to connect to providers; and also to state which quale-iface APIs it exports.
*/
class StimBuffApiDesc
{
public:
class ExportedQualeIfaceApiDesc
{
public:
static bool sanityCheck(const ExportedQualeIfaceApiDesc &desc)
{
if (desc.name.empty()) { return false; }
return true;
}
public:
std::string name;
};
public:
std::string stringify() const
{
std::string result = "Name: " + name + "\n";
result += "Exported QualeIface APIs:\n";
for (const auto& api : exportedQualeIfaceApis) {
result += " - " + api.name + "\n";
}
return result;
}
static bool sanityCheck(const StimBuffApiDesc &desc)
{
if (desc.name.empty() || desc.exportedQualeIfaceApis.empty()) {
return false;
}
for (const auto& api : desc.exportedQualeIfaceApis) {
if (!ExportedQualeIfaceApiDesc::sanityCheck(api)) { return false; }
}
return Sal_Mgmt_LibOps::sanityCheck(desc.sal_mgmt_libOps);
}
std::string name;
// These are the quale-iface APIs this lib exports.
std::vector<ExportedQualeIfaceApiDesc> exportedQualeIfaceApis;
Sal_Mgmt_LibOps sal_mgmt_libOps;
};
#define SMO_GET_STIM_BUFF_API_DESC_FN_NAME getStimBuffApiDesc
#define SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR \
SMO_QUOTE(SMO_GET_STIM_BUFF_API_DESC_FN_NAME)
#define SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF \
SMO_CONCAT(SMO_GET_STIM_BUFF_API_DESC_FN_NAME, Fn)
/* Every Stim Buff API library must define a global instance of this
* function. Salmanoff will search for it and invoke it via dlsym().
*
* The function must return a StimBuffApiDesc struct that Smo will tell
* Smo what quale-iface APIs can be used with it & what APIs it exports.
* The StimBuffApiDesc struct also gives Smo pointers to API functions
* to invoke for communication between Smo and the library.
*
* The SmoCallbacks parameter provides the library with access to
* Salmanoff's hooks.
* The SmoThreadingModelDesc parameter provides the library with access to
* the io_service for network operations and event handling.
*/
typedef const StimBuffApiDesc &(SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF)(
const SmoCallbacks& callbacks,
const SmoThreadingModelDesc& threadingModel);
} // namespace stim_buff
} // namespace smo
#endif // __USER_SENSE_API_LIB_H__