[Beignet] [PATCH 13/57] Add cl_context define to runtime.
junyan.he at inbox.com
junyan.he at inbox.com
Sun Jun 11 05:49:59 UTC 2017
From: Junyan He <junyan.he at intel.com>
Signed-off-by: Junyan He <junyan.he at intel.com>
---
runtime/cl_context.c | 436 +++++++++++++++++++++++++++++++++++++++++++++++++++
runtime/cl_context.h | 105 +++++++++++++
2 files changed, 541 insertions(+)
create mode 100644 runtime/cl_context.c
create mode 100644 runtime/cl_context.h
diff --git a/runtime/cl_context.c b/runtime/cl_context.c
new file mode 100644
index 0000000..46ff7ed
--- /dev/null
+++ b/runtime/cl_context.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cl_platform_id.h"
+#include "cl_device_id.h"
+#include "cl_context.h"
+#include "cl_command_queue.h"
+#include "cl_sampler.h"
+#include "cl_event.h"
+#include "cl_alloc.h"
+#include "cl_utils.h"
+#include "cl_mem.h"
+#include "cl_khr_icd.h"
+#include "cl_program.h"
+#include "CL/cl_gl.h"
+#include <string.h>
+
+LOCAL void
+cl_context_add_queue(cl_context ctx, cl_command_queue queue)
+{
+ assert(queue->ctx == NULL);
+ cl_context_add_ref(ctx);
+
+ CL_OBJECT_LOCK(ctx);
+ while (ctx->queue_modify_disable) {
+ CL_OBJECT_WAIT_ON_COND(ctx);
+ }
+ list_add_tail(&ctx->queues, &queue->base.node);
+ ctx->queue_num++;
+ CL_OBJECT_UNLOCK(ctx);
+
+ queue->ctx = ctx;
+}
+
+LOCAL void
+cl_context_remove_queue(cl_context ctx, cl_command_queue queue)
+{
+ assert(queue->ctx == ctx);
+
+ CL_OBJECT_LOCK(ctx);
+ while (ctx->queue_modify_disable) {
+ CL_OBJECT_WAIT_ON_COND(ctx);
+ }
+ list_node_del(&queue->base.node);
+ ctx->queue_num--;
+ CL_OBJECT_UNLOCK(ctx);
+
+ cl_context_delete(ctx);
+ queue->ctx = NULL;
+}
+
+LOCAL void
+cl_context_add_mem(cl_context ctx, cl_mem mem)
+{
+ assert(mem->ctx == NULL);
+ cl_context_add_ref(ctx);
+
+ CL_OBJECT_LOCK(ctx);
+ list_add_tail(&ctx->mem_objects, &mem->base.node);
+ ctx->mem_object_num++;
+ CL_OBJECT_UNLOCK(ctx);
+
+ mem->ctx = ctx;
+}
+
+LOCAL void
+cl_context_remove_mem(cl_context ctx, cl_mem mem)
+{
+ assert(mem->ctx == ctx);
+ CL_OBJECT_LOCK(ctx);
+ list_node_del(&mem->base.node);
+ ctx->mem_object_num--;
+ CL_OBJECT_UNLOCK(ctx);
+
+ cl_context_delete(ctx);
+ mem->ctx = NULL;
+}
+
+LOCAL void
+cl_context_add_sampler(cl_context ctx, cl_sampler sampler)
+{
+ assert(sampler->ctx == NULL);
+ cl_context_add_ref(ctx);
+
+ CL_OBJECT_LOCK(ctx);
+ list_add_tail(&ctx->samplers, &sampler->base.node);
+ ctx->sampler_num++;
+ CL_OBJECT_UNLOCK(ctx);
+
+ sampler->ctx = ctx;
+}
+
+LOCAL void
+cl_context_remove_sampler(cl_context ctx, cl_sampler sampler)
+{
+ assert(sampler->ctx == ctx);
+ CL_OBJECT_LOCK(ctx);
+ list_node_del(&sampler->base.node);
+ ctx->sampler_num--;
+ CL_OBJECT_UNLOCK(ctx);
+
+ cl_context_delete(ctx);
+ sampler->ctx = NULL;
+}
+
+LOCAL void
+cl_context_add_event(cl_context ctx, cl_event event)
+{
+ assert(event->ctx == NULL);
+ cl_context_add_ref(ctx);
+
+ CL_OBJECT_LOCK(ctx);
+ list_add_tail(&ctx->events, &event->base.node);
+ ctx->event_num++;
+ CL_OBJECT_UNLOCK(ctx);
+
+ event->ctx = ctx;
+}
+
+LOCAL void
+cl_context_remove_event(cl_context ctx, cl_event event)
+{
+ assert(event->ctx == ctx);
+ CL_OBJECT_LOCK(ctx);
+ list_node_del(&event->base.node);
+ ctx->event_num--;
+ CL_OBJECT_UNLOCK(ctx);
+
+ cl_context_delete(ctx);
+ event->ctx = NULL;
+}
+
+LOCAL void
+cl_context_add_program(cl_context ctx, cl_program program)
+{
+ assert(program->ctx == NULL);
+ cl_context_add_ref(ctx);
+
+ CL_OBJECT_LOCK(ctx);
+ list_add_tail(&ctx->programs, &program->base.node);
+ ctx->program_num++;
+ CL_OBJECT_UNLOCK(ctx);
+
+ program->ctx = ctx;
+}
+
+LOCAL void
+cl_context_remove_program(cl_context ctx, cl_program program)
+{
+ assert(program->ctx == ctx);
+ CL_OBJECT_LOCK(ctx);
+ list_node_del(&program->base.node);
+ ctx->program_num--;
+ CL_OBJECT_UNLOCK(ctx);
+
+ cl_context_delete(ctx);
+ program->ctx = NULL;
+}
+
+static cl_int
+cl_context_properties_process(const cl_context_properties *prop,
+ struct _cl_context_prop *cl_props, cl_uint *prop_len)
+{
+#define CHECK(var) \
+ if (var) \
+ return CL_INVALID_PROPERTY; \
+ else \
+ var = 1;
+
+ int set_cl_context_platform = 0,
+ set_cl_gl_context_khr = 0,
+ set_cl_egl_display_khr = 0,
+ set_cl_glx_display_khr = 0,
+ set_cl_wgl_hdc_khr = 0,
+ set_cl_cgl_sharegroup_khr = 0;
+ cl_int err = CL_SUCCESS;
+
+ cl_props->gl_type = CL_GL_NOSHARE;
+ cl_props->platform_id = 0;
+
+ if (prop == NULL)
+ goto error;
+
+ while (*prop) {
+ switch (*prop) {
+ case CL_CONTEXT_PLATFORM:
+ CHECK(set_cl_context_platform);
+ cl_props->platform_id = *(prop + 1);
+ if (UNLIKELY((cl_platform_id)cl_props->platform_id != cl_get_platform_default())) {
+ err = CL_INVALID_PLATFORM;
+ goto error;
+ }
+ break;
+ case CL_GL_CONTEXT_KHR:
+ CHECK(set_cl_gl_context_khr);
+ cl_props->gl_context = *(prop + 1);
+ break;
+ case CL_EGL_DISPLAY_KHR:
+ CHECK(set_cl_egl_display_khr);
+ cl_props->gl_type = CL_GL_EGL_DISPLAY;
+ cl_props->egl_display = *(prop + 1);
+ break;
+ case CL_GLX_DISPLAY_KHR:
+ CHECK(set_cl_glx_display_khr);
+ cl_props->gl_type = CL_GL_GLX_DISPLAY;
+ cl_props->glx_display = *(prop + 1);
+ break;
+ case CL_WGL_HDC_KHR:
+ CHECK(set_cl_wgl_hdc_khr);
+ cl_props->gl_type = CL_GL_WGL_HDC;
+ cl_props->wgl_hdc = *(prop + 1);
+ break;
+ case CL_CGL_SHAREGROUP_KHR:
+ CHECK(set_cl_cgl_sharegroup_khr);
+ cl_props->gl_type = CL_GL_CGL_SHAREGROUP;
+ cl_props->cgl_sharegroup = *(prop + 1);
+ break;
+ default:
+ err = CL_INVALID_PROPERTY;
+ goto error;
+ }
+ prop += 2;
+ *prop_len += 2;
+ }
+ (*prop_len)++;
+
+error:
+ return err;
+
+#undef CHECK
+}
+
+static cl_context
+cl_context_new(struct _cl_context_prop *props, cl_uint dev_num, cl_device_id *all_dev)
+{
+ cl_context ctx = NULL;
+
+ ctx = CL_CALLOC(1, sizeof(_cl_context));
+ if (ctx == NULL)
+ return NULL;
+
+ CL_OBJECT_INIT_BASE(ctx, CL_OBJECT_CONTEXT_MAGIC);
+ ctx->device_num = dev_num;
+ ctx->devices = CL_MALLOC(dev_num * sizeof(cl_device_id));
+ if (ctx->devices == NULL) {
+ CL_FREE(ctx);
+ return NULL;
+ }
+ memcpy(ctx->devices, all_dev, dev_num * sizeof(cl_device_id));
+
+ ctx->props = *props;
+ list_init(&ctx->queues);
+ list_init(&ctx->mem_objects);
+ list_init(&ctx->samplers);
+ list_init(&ctx->events);
+ list_init(&ctx->programs);
+ ctx->queue_modify_disable = 0;
+
+ ctx->each_device = CL_CALLOC(ctx->device_num, sizeof(cl_context_for_device));
+ if (ctx->each_device == NULL) {
+ CL_FREE(ctx);
+ return NULL;
+ }
+
+ ctx->each_device_num = ctx->device_num;
+ return ctx;
+}
+
+LOCAL void
+cl_context_delete(cl_context ctx)
+{
+ cl_int i = 0;
+
+ if (ctx == NULL)
+ return;
+
+ /* We are not done yet */
+ if (CL_OBJECT_DEC_REF(ctx) > 1)
+ return;
+
+ assert(ctx->devices);
+ for (i = 0; i < ctx->each_device_num; i++) {
+ if (ctx->each_device[i])
+ (ctx->each_device[i]->device->api.context_delete)(ctx->each_device[i]->device, ctx);
+ }
+ CL_FREE(ctx->each_device);
+ ctx->each_device = NULL;
+
+ if (ctx->prop_user) {
+ CL_FREE(ctx->prop_user);
+ ctx->prop_user = NULL;
+ }
+
+ CL_FREE(ctx->devices);
+ ctx->devices = NULL;
+
+ CL_OBJECT_DESTROY_BASE(ctx);
+ CL_FREE(ctx);
+}
+
+LOCAL cl_context
+cl_context_create(const cl_context_properties *properties,
+ cl_uint num_devices,
+ const cl_device_id *devices,
+ void(CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *),
+ void *user_data,
+ cl_int *errcode_ret)
+{
+ /* cl_platform_id platform = NULL; */
+ struct _cl_context_prop props;
+ cl_context ctx = NULL;
+ cl_int err = CL_SUCCESS;
+ cl_uint prop_len = 0;
+ cl_uint dev_num = 0;
+ cl_device_id *all_dev = NULL;
+ cl_uint i, j;
+
+ assert(num_devices > 0);
+
+ /* Check that we are getting the right platform */
+ if ((err = cl_context_properties_process(properties, &props, &prop_len)) != CL_SUCCESS) {
+ *errcode_ret = err;
+ return NULL;
+ }
+
+ all_dev = CL_CALLOC(num_devices, sizeof(cl_device_id));
+ if (all_dev == NULL) {
+ *errcode_ret = CL_OUT_OF_HOST_MEMORY;
+ return NULL;
+ }
+
+ /* Filter out repeated device. */
+ for (i = 0; i < num_devices; i++) {
+ for (j = 0; j < i; j++) {
+ if (devices[j] == devices[i]) {
+ break;
+ }
+ }
+
+ if (j != i) { // Find some duplicated one.
+ continue;
+ }
+
+ all_dev[dev_num] = devices[i];
+ dev_num++;
+ }
+
+ /* We are good */
+ ctx = cl_context_new(&props, dev_num, all_dev);
+ CL_FREE(all_dev);
+ if (ctx == NULL) {
+ *errcode_ret = CL_OUT_OF_HOST_MEMORY;
+ return NULL;
+ }
+
+ if (properties != NULL && prop_len > 0) {
+ ctx->prop_user = CL_MALLOC(sizeof(cl_context_properties) * prop_len);
+ if (ctx->prop_user == NULL) {
+ cl_context_delete(ctx);
+ *errcode_ret = CL_OUT_OF_HOST_MEMORY;
+ return NULL;
+ }
+ memcpy(ctx->prop_user, properties, sizeof(cl_context_properties) * prop_len);
+ }
+
+ ctx->prop_len = prop_len;
+ /* Save the user callback and user data*/
+ ctx->pfn_notify = pfn_notify;
+ ctx->user_data = user_data;
+
+ for (i = 0; i < ctx->device_num; i++) {
+ err = (ctx->devices[i]->api.context_create)(ctx->devices[i], ctx);
+ if (err != CL_SUCCESS) {
+ *errcode_ret = err;
+ cl_context_delete(ctx);
+ return NULL;
+ }
+ }
+
+ *errcode_ret = err;
+ return ctx;
+}
+
+LOCAL void
+cl_context_add_ref(cl_context ctx)
+{
+ assert(ctx);
+ CL_OBJECT_INC_REF(ctx);
+}
+
+LOCAL cl_mem
+cl_context_get_svm_by_ptr(cl_context ctx, const void *p, cl_bool no_offset)
+{
+ struct list_node *pos;
+ cl_mem buf = NULL;
+
+ CL_OBJECT_LOCK(ctx);
+ list_for_each(pos, (&ctx->mem_objects))
+ {
+ buf = (cl_mem)list_entry(pos, _cl_base_object, node);
+ if (!CL_OBJECT_IS_SVM(buf))
+ continue;
+
+ assert(buf->host_ptr != NULL);
+
+ if (no_offset) {
+ if (p == buf->host_ptr) {
+ CL_OBJECT_UNLOCK(ctx);
+ return buf;
+ }
+ } else {
+ if (p >= buf->host_ptr && p < buf->host_ptr + buf->size) {
+ CL_OBJECT_UNLOCK(ctx);
+ return buf;
+ }
+ }
+ }
+ CL_OBJECT_UNLOCK(ctx);
+
+ return NULL;
+}
diff --git a/runtime/cl_context.h b/runtime/cl_context.h
new file mode 100644
index 0000000..f58558d
--- /dev/null
+++ b/runtime/cl_context.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __CL_CONTEXT_H__
+#define __CL_CONTEXT_H__
+
+#include "cl_base_object.h"
+#include "CL/cl.h"
+#include "CL/cl_ext.h"
+
+enum _cl_gl_context_type {
+ CL_GL_NOSHARE,
+ CL_GL_EGL_DISPLAY,
+ CL_GL_GLX_DISPLAY,
+ CL_GL_WGL_HDC,
+ CL_GL_CGL_SHAREGROUP
+};
+
+typedef struct _cl_context_prop {
+ cl_context_properties platform_id;
+ enum _cl_gl_context_type gl_type;
+ cl_context_properties gl_context;
+ union {
+ cl_context_properties egl_display;
+ cl_context_properties glx_display;
+ cl_context_properties wgl_hdc;
+ cl_context_properties cgl_sharegroup;
+ };
+} _cl_context_prop;
+typedef _cl_context_prop *cl_context_prop;
+
+typedef struct _cl_context_for_device {
+ cl_device_id device; /* Point to the device it belong to */
+} _cl_context_for_device;
+typedef _cl_context_for_device *cl_context_for_device;
+
+typedef struct _cl_context {
+ _cl_base_object base;
+ cl_device_id *devices; /* All devices belong to this context */
+ cl_uint device_num; /* Devices number of this context */
+ list_head queues; /* All command queues currently allocated */
+ cl_uint queue_num; /* All queue number currently allocated */
+ cl_uint queue_modify_disable; /* Temp disable queue list change. */
+ list_head mem_objects; /* All memory object currently allocated */
+ cl_uint mem_object_num; /* All memory number currently allocated */
+ list_head samplers; /* All sampler object currently allocated */
+ cl_uint sampler_num; /* All sampler number currently allocated */
+ list_head events; /* All event object currently allocated */
+ cl_uint event_num; /* All event number currently allocated */
+ list_head programs; /* All programs currently allocated */
+ cl_uint program_num; /* All program number currently allocated */
+
+ struct _cl_context_prop props;
+ cl_context_properties *prop_user; /* a copy of user passed context properties when create context */
+ cl_uint prop_len; /* count of the properties */
+
+ cl_uint each_device_num; /* Each device number */
+ cl_context_for_device *each_device; /* Context content interpreted by device */
+
+ void(CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *);
+ /* User's callback when error occur in context */
+ void *user_data; /* A pointer to user supplied data */
+} _cl_context;
+
+#define CL_OBJECT_CONTEXT_MAGIC 0x20BBCADE993134AALL
+#define CL_OBJECT_IS_CONTEXT(obj) ((obj && \
+ ((cl_base_object)obj)->magic == CL_OBJECT_CONTEXT_MAGIC && \
+ CL_OBJECT_GET_REF(obj) >= 1))
+#define CL_OBJECT_IS_CONTEXT_EGL(obj) ((obj && \
+ ((cl_base_object)obj)->magic == CL_OBJECT_CONTEXT_MAGIC && \
+ CL_OBJECT_GET_REF(obj) >= 1) && \
+ ((cl_context)obj)->props.gl_type == CL_GL_EGL_DISPLAY)
+
+extern void cl_context_add_queue(cl_context ctx, cl_command_queue queue);
+extern void cl_context_remove_queue(cl_context ctx, cl_command_queue queue);
+extern void cl_context_add_mem(cl_context ctx, cl_mem mem);
+extern void cl_context_remove_mem(cl_context ctx, cl_mem mem);
+extern void cl_context_add_sampler(cl_context ctx, cl_sampler sampler);
+extern void cl_context_remove_sampler(cl_context ctx, cl_sampler sampler);
+extern void cl_context_add_event(cl_context ctx, cl_event sampler);
+extern void cl_context_remove_event(cl_context ctx, cl_event sampler);
+extern void cl_context_add_program(cl_context ctx, cl_program program);
+extern void cl_context_remove_program(cl_context ctx, cl_program program);
+extern cl_context cl_context_create(const cl_context_properties *, cl_uint, const cl_device_id *,
+ void(CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *),
+ void *, cl_int *);
+extern void cl_context_delete(cl_context);
+extern void cl_context_add_ref(cl_context);
+extern cl_mem cl_context_get_svm_by_ptr(cl_context ctx, const void *p, cl_bool no_offset);
+#endif /* __CL_CONTEXT_H__ */
--
2.7.4
More information about the Beignet
mailing list