Hash :
44a5c913
Author :
Date :
2021-06-17T09:29:29
CL: Make CL front end and back end thread-safe Add locking to all mutable variables of the CL objects in the front end and pass-through back end to make them thread-safe. This fixes a crash in a multi-threaded CTS test. Bug: angleproject:6015 Change-Id: I1d6471c851217639411c434c82acd32d14035291 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2967468 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLProgram.h: Defines the cl::Program class, which consists of a set of OpenCL kernels.
#ifndef LIBANGLE_CLPROGRAM_H_
#define LIBANGLE_CLPROGRAM_H_
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLKernel.h"
#include "libANGLE/renderer/CLProgramImpl.h"
#include "common/Spinlock.h"
#include "common/SynchronizedValue.h"
#include <atomic>
namespace cl
{
class Program final : public _cl_program, public Object
{
public:
// Front end entry functions, only called from OpenCL entry points
cl_int build(cl_uint numDevices,
const cl_device_id *deviceList,
const char *options,
ProgramCB pfnNotify,
void *userData);
cl_int compile(cl_uint numDevices,
const cl_device_id *deviceList,
const char *options,
cl_uint numInputHeaders,
const cl_program *inputHeaders,
const char **headerIncludeNames,
ProgramCB pfnNotify,
void *userData);
cl_int getInfo(ProgramInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const;
cl_int getBuildInfo(cl_device_id device,
ProgramBuildInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const;
cl_kernel createKernel(const char *kernel_name, cl_int &errorCode);
cl_int createKernels(cl_uint numKernels, cl_kernel *kernels, cl_uint *numKernelsRet);
public:
~Program() override;
Context &getContext();
const Context &getContext() const;
const DevicePtrs &getDevices() const;
bool hasDevice(const _cl_device_id *device) const;
bool isBuilding() const;
bool hasAttachedKernels() const;
template <typename T = rx::CLProgramImpl>
T &getImpl() const;
void callback();
private:
Program(Context &context, std::string &&source, cl_int &errorCode);
Program(Context &context, const void *il, size_t length, cl_int &errorCode);
Program(Context &context,
DevicePtrs &&devices,
const size_t *lengths,
const unsigned char **binaries,
cl_int *binaryStatus,
cl_int &errorCode);
Program(Context &context, DevicePtrs &&devices, const char *kernelNames, cl_int &errorCode);
Program(Context &context,
const DevicePtrs &devices,
const char *options,
const cl::ProgramPtrs &inputPrograms,
ProgramCB pfnNotify,
void *userData,
cl_int &errorCode);
using CallbackData = std::pair<ProgramCB, void *>;
const ContextPtr mContext;
const DevicePtrs mDevices;
const std::string mIL;
// mCallback might be accessed from implementation initialization
// and needs to be initialized first.
angle::SynchronizedValue<CallbackData, angle::Spinlock> mCallback;
std::atomic<cl_uint> mNumAttachedKernels;
const rx::CLProgramImpl::Ptr mImpl;
const std::string mSource;
friend class Kernel;
friend class Object;
};
inline Context &Program::getContext()
{
return *mContext;
}
inline const Context &Program::getContext() const
{
return *mContext;
}
inline const DevicePtrs &Program::getDevices() const
{
return mDevices;
}
inline bool Program::hasDevice(const _cl_device_id *device) const
{
return std::find(mDevices.cbegin(), mDevices.cend(), device) != mDevices.cend();
}
inline bool Program::isBuilding() const
{
return mCallback->first != nullptr;
}
inline bool Program::hasAttachedKernels() const
{
return mNumAttachedKernels != 0u;
}
template <typename T>
inline T &Program::getImpl() const
{
return static_cast<T &>(*mImpl);
}
} // namespace cl
#endif // LIBANGLE_CLPROGRAM_H_