/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include #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 platforms; err = cl::Platform::get(&platforms); if (err != CL_SUCCESS) { AppendLog(L"Platform::get() failed\n"); return -1; } std::vector::iterator i; if (platforms.size() > 0) { for (i = platforms.begin(); i != platforms.end(); ++i) { if (!strcmp((*i).getInfo(&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 devices = context.getInfo(); 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(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; }