CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
305 lines
8.8 KiB
C++
305 lines
8.8 KiB
C++
/*
|
|
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS 1
|
|
#include "CL/cl.hpp"
|
|
|
|
SERVICE_STATUS serviceStatus = {0};
|
|
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
|
|
|
|
const wchar_t* CrossProcessEventName = L"Global\\OpenCL_Test_serviceEvent";
|
|
const wchar_t* successMessage = L"OpenCL Service Test Success\n";
|
|
const wchar_t* serviceName = L"OpenCL Test service";
|
|
// this event is set whenever the service thread is finished executing
|
|
// all it's tasks
|
|
HANDLE RetireServiceEvent = 0;
|
|
|
|
DWORD WINAPI ThreadProc(LPVOID lpdwThreadParam);
|
|
|
|
//////////////////////////
|
|
// log relate functions //
|
|
//////////////////////////
|
|
void getLogFileName(wchar_t fileName[MAX_PATH]) {
|
|
DWORD dwSize = GetModuleFileNameW(NULL, fileName, MAX_PATH);
|
|
wchar_t* p = fileName + dwSize;
|
|
while (*p != '\\' && p > fileName) p--;
|
|
p++;
|
|
wcscpy(p, L"result.txt");
|
|
}
|
|
|
|
VOID WriteLog(const wchar_t* pMsg) {
|
|
static wchar_t fileName[MAX_PATH] = {0};
|
|
if (fileName[0] == 0) getLogFileName(fileName);
|
|
|
|
FILE* pLog = _wfopen(fileName, L"w");
|
|
if (NULL != pLog) {
|
|
fwprintf(pLog, pMsg);
|
|
fclose(pLog);
|
|
}
|
|
}
|
|
|
|
VOID AppendLog(const wchar_t* pMsg) {
|
|
static wchar_t fileName[MAX_PATH] = {0};
|
|
if (fileName[0] == 0) getLogFileName(fileName);
|
|
FILE* pLog = _wfopen(fileName, L"a");
|
|
if (NULL != pLog) {
|
|
fwprintf(pLog, pMsg);
|
|
fclose(pLog);
|
|
}
|
|
}
|
|
|
|
VOID AppendLog(const char* pMsg) {
|
|
static wchar_t fileName[MAX_PATH] = {0};
|
|
if (fileName[0] == 0) getLogFileName(fileName);
|
|
FILE* pLog = _wfopen(fileName, L"a");
|
|
if (NULL != pLog) {
|
|
fprintf(pLog, pMsg);
|
|
fclose(pLog);
|
|
}
|
|
}
|
|
///////////////////////////////
|
|
// service related functions //
|
|
///////////////////////////////
|
|
void WINAPI ServiceControlHandler(DWORD controlCode) {
|
|
switch (controlCode) {
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
break;
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN:
|
|
case SERVICE_CONTROL_STOP:
|
|
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
|
if (!SetServiceStatus(serviceStatusHandle, &serviceStatus))
|
|
AppendLog(L"SetServiceStatus SERVICE_STOP_PENDING failed\n");
|
|
|
|
if (RetireServiceEvent) SetEvent(RetireServiceEvent);
|
|
return;
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
break;
|
|
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
break;
|
|
|
|
default:
|
|
if (controlCode >= 128 && controlCode <= 255)
|
|
// user defined control code
|
|
break;
|
|
else
|
|
// unrecognised control code
|
|
break;
|
|
}
|
|
|
|
if (!SetServiceStatus(serviceStatusHandle, &serviceStatus))
|
|
AppendLog(L"SetServiceStatus SERVICE_STOP_PENDING failed\n");
|
|
}
|
|
|
|
void WINAPI ServiceMain(DWORD /*argc*/, wchar_t* /*argv*/[]) {
|
|
// initialise service status
|
|
serviceStatus.dwServiceType = SERVICE_WIN32;
|
|
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN;
|
|
serviceStatus.dwWin32ExitCode = NO_ERROR;
|
|
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
|
|
serviceStatus.dwCheckPoint = 0;
|
|
serviceStatus.dwWaitHint = 0;
|
|
|
|
serviceStatusHandle = RegisterServiceCtrlHandlerW(serviceName, ServiceControlHandler);
|
|
|
|
if (serviceStatusHandle) {
|
|
// service is starting
|
|
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
if (!SetServiceStatus(serviceStatusHandle, &serviceStatus))
|
|
AppendLog(L"SetServiceStatus SERVICE_START_PENDING failed\n");
|
|
|
|
// do initialisation here
|
|
RetireServiceEvent = CreateEvent(0, FALSE, FALSE, 0);
|
|
|
|
// running
|
|
serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
|
serviceStatus.dwCurrentState = SERVICE_RUNNING;
|
|
if (!SetServiceStatus(serviceStatusHandle, &serviceStatus))
|
|
AppendLog(L"SetServiceStatus SERVICE_RUNNING failed\n");
|
|
|
|
// Create the thread that actually does the CL testing
|
|
CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
|
|
// wait for the thread to finish
|
|
WaitForSingleObject(RetireServiceEvent, 60000);
|
|
|
|
HANDLE crossProcessEvent = OpenEventW(EVENT_ALL_ACCESS, FALSE, CrossProcessEventName);
|
|
if (NULL != crossProcessEvent) {
|
|
SetEvent(crossProcessEvent);
|
|
} else {
|
|
AppendLog(L"cross process Event could not be openned\n");
|
|
}
|
|
|
|
// service was stopped
|
|
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
|
if (!SetServiceStatus(serviceStatusHandle, &serviceStatus))
|
|
AppendLog(L"SetServiceStatus SERVICE_STOP_PENDING failed\n");
|
|
|
|
// do cleanup here
|
|
CloseHandle(crossProcessEvent);
|
|
CloseHandle(RetireServiceEvent);
|
|
RetireServiceEvent = 0;
|
|
|
|
// service is now stopped
|
|
serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
|
serviceStatus.dwCurrentState = SERVICE_STOPPED;
|
|
if (!SetServiceStatus(serviceStatusHandle, &serviceStatus))
|
|
AppendLog(L"SetServiceStatus SERVICE_STOPPED failed\n");
|
|
}
|
|
}
|
|
|
|
// This function services ocltst as a service when launched
|
|
// by the OS. It registers the service routines.
|
|
void serviceStubCall() {
|
|
wchar_t serviceName[MAX_PATH];
|
|
wcscpy(serviceName, ::serviceName);
|
|
SERVICE_TABLE_ENTRYW serviceTable[] = {{serviceName, ServiceMain}, {0, 0}};
|
|
DWORD session_id;
|
|
BOOL retVal = ProcessIdToSessionId(GetCurrentProcessId(), &session_id);
|
|
if (0 == session_id) {
|
|
StartServiceCtrlDispatcherW(serviceTable);
|
|
}
|
|
}
|
|
/////////////////////
|
|
// CL related code //
|
|
/////////////////////
|
|
const char c_kernelCode[] =
|
|
" __kernel void hello(__global char * theArray)"
|
|
"{"
|
|
" size_t i = get_global_id(0);"
|
|
"if ( i < get_global_size(0))"
|
|
"theArray[i] = 78;"
|
|
"}";
|
|
|
|
const unsigned int c_bufferSize = 1024;
|
|
|
|
DWORD WINAPI ThreadProc(LPVOID lpdwThreadParam) {
|
|
cl_int err;
|
|
// Platform info
|
|
std::vector<cl::Platform> platforms;
|
|
|
|
err = cl::Platform::get(&platforms);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Platform::get() failed\n");
|
|
return -1;
|
|
}
|
|
|
|
std::vector<cl::Platform>::iterator i;
|
|
if (platforms.size() > 0) {
|
|
for (i = platforms.begin(); i != platforms.end(); ++i) {
|
|
if (!strcmp((*i).getInfo<CL_PLATFORM_VENDOR>(&err).c_str(), "Advanced Micro Devices, Inc.")) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Platform::getInfo() failed \n");
|
|
return -1;
|
|
}
|
|
|
|
cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(*i)(), 0};
|
|
|
|
cl::Context context(CL_DEVICE_TYPE_GPU, cps, NULL, NULL, &err);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Context::Context() failed \n");
|
|
return -1;
|
|
}
|
|
|
|
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Context::getInfo() failed \n");
|
|
return -1;
|
|
}
|
|
if (devices.size() == 0) {
|
|
AppendLog(L"No device available\n");
|
|
return -1;
|
|
}
|
|
|
|
cl::Program::Sources sources(1, std::make_pair(c_kernelCode, sizeof(c_kernelCode)));
|
|
|
|
cl::Program program = cl::Program(context, sources, &err);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Program::Program() failed\n");
|
|
}
|
|
|
|
err = program.build(devices);
|
|
if (err != CL_SUCCESS) {
|
|
if (err == CL_BUILD_PROGRAM_FAILURE) {
|
|
std::string str((char*)program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]).c_str());
|
|
|
|
AppendLog(L" \n\t\t\tBUILD LOG\n\n");
|
|
AppendLog(L" ************************************************\n");
|
|
AppendLog(str.c_str());
|
|
AppendLog(L" ************************************************\n");
|
|
}
|
|
|
|
AppendLog(L"Program::build() failed\n");
|
|
return -1;
|
|
}
|
|
|
|
cl::Kernel kernel(program, "hello", &err);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Kernel::Kernel() failed\n");
|
|
return -1;
|
|
}
|
|
|
|
cl::Buffer buffer = cl::Buffer(context, CL_MEM_READ_WRITE, c_bufferSize, 0, &err);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Kernel::setArg() failed \n");
|
|
}
|
|
|
|
cl::CommandQueue queue(context, devices[0], 0, &err);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"CommandQueue::CommandQueue() failed \n");
|
|
return -1;
|
|
}
|
|
|
|
err = kernel.setArg(0, buffer);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Kernel::setArg() failed \n");
|
|
return -1;
|
|
}
|
|
|
|
err = queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(c_bufferSize), cl::NullRange);
|
|
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"CommandQueue::enqueueNDRangeKernel()\n");
|
|
return -1;
|
|
}
|
|
|
|
err = queue.finish();
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"Event::wait() failed \n");
|
|
}
|
|
char* ptr = (char*)malloc(c_bufferSize);
|
|
err = queue.enqueueReadBuffer(buffer, CL_TRUE, 0, c_bufferSize, ptr, NULL, NULL);
|
|
if (err != CL_SUCCESS) {
|
|
AppendLog(L"CommandQueue::enqueueReadBuffer()\n");
|
|
return -1;
|
|
}
|
|
|
|
bool validateSuccess = true;
|
|
// validate the results
|
|
for (int i = 0; i < c_bufferSize; i++) {
|
|
if (ptr[i] != 78) validateSuccess = false;
|
|
}
|
|
|
|
free(ptr);
|
|
if (validateSuccess) {
|
|
WriteLog(successMessage);
|
|
AppendLog(L"validate success");
|
|
} else {
|
|
AppendLog(L"Validate fail");
|
|
return -1;
|
|
}
|
|
|
|
SetEvent(RetireServiceEvent);
|
|
return 0;
|
|
}
|