[Beignet] [PATCH 08/57] Add base object file to runtime.
junyan.he at inbox.com
junyan.he at inbox.com
Sun Jun 11 05:49:54 UTC 2017
From: Junyan He <junyan.he at intel.com>
The cl_base_object will be the base class for all cl runtime
objects such as cl_mem, cl_kernel, cl_program.
Signed-off-by: Junyan He <junyan.he at intel.com>
---
runtime/cl_base_object.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++
runtime/cl_base_object.h | 85 +++++++++++++++++++++++
2 files changed, 261 insertions(+)
create mode 100644 runtime/cl_base_object.c
create mode 100644 runtime/cl_base_object.h
diff --git a/runtime/cl_base_object.c b/runtime/cl_base_object.c
new file mode 100644
index 0000000..718c606
--- /dev/null
+++ b/runtime/cl_base_object.c
@@ -0,0 +1,176 @@
+/*
+ * 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 <stdio.h>
+#include "cl_base_object.h"
+#include "cl_alloc.h"
+
+static pthread_t invalid_thread_id = -1;
+
+LOCAL void
+cl_object_init_base(cl_base_object obj, cl_ulong magic)
+{
+ obj->magic = magic;
+ obj->ref = 1;
+ SET_ICD(obj->dispatch);
+ pthread_mutex_init(&obj->mutex, NULL);
+ pthread_cond_init(&obj->cond, NULL);
+ obj->owner = invalid_thread_id;
+ list_node_init(&obj->node);
+}
+
+LOCAL void
+cl_object_destroy_base(cl_base_object obj)
+{
+ int ref = CL_OBJECT_GET_REF(obj);
+ if (ref != 0) {
+ CL_LOG_ERROR("CL object %p, call destroy with a reference %d", obj, ref);
+ assert(0);
+ }
+
+ if (!CL_OBJECT_IS_VALID(obj)) {
+ CL_LOG_ERROR("CL object %p, call destroy while it is already a dead object", obj);
+ assert(0);
+ }
+
+ if (obj->owner != invalid_thread_id) {
+ CL_LOG_ERROR("CL object %p, call destroy while still has a owener %d", obj, (int)obj->owner);
+ assert(0);
+ }
+
+ if (!list_node_out_of_list(&obj->node)) {
+ CL_LOG_ERROR("CL object %p, call destroy while still belong to some object %p", obj, obj->node.p);
+ assert(0);
+ }
+
+ obj->magic = CL_OBJECT_INVALID_MAGIC;
+ pthread_mutex_destroy(&obj->mutex);
+ pthread_cond_destroy(&obj->cond);
+}
+
+LOCAL cl_int
+cl_object_take_ownership(cl_base_object obj, cl_int wait, cl_bool withlock)
+{
+ pthread_t self;
+
+ assert(CL_OBJECT_IS_VALID(obj));
+
+ self = pthread_self();
+
+ if (withlock == CL_FALSE)
+ pthread_mutex_lock(&obj->mutex);
+
+ if (pthread_equal(obj->owner, self)) { // Already get
+ if (withlock == CL_FALSE)
+ pthread_mutex_unlock(&obj->mutex);
+ return 1;
+ }
+
+ if (pthread_equal(obj->owner, invalid_thread_id)) {
+ obj->owner = self;
+
+ if (withlock == CL_FALSE)
+ pthread_mutex_unlock(&obj->mutex);
+ return 1;
+ }
+
+ if (wait == 0) {
+ if (withlock == CL_FALSE)
+ pthread_mutex_unlock(&obj->mutex);
+ return 0;
+ }
+
+ while (!pthread_equal(obj->owner, invalid_thread_id)) {
+ pthread_cond_wait(&obj->cond, &obj->mutex);
+ }
+
+ obj->owner = self;
+
+ if (withlock == CL_FALSE)
+ pthread_mutex_unlock(&obj->mutex);
+
+ return 1;
+}
+
+LOCAL void
+cl_object_release_ownership(cl_base_object obj, cl_bool withlock)
+{
+ assert(CL_OBJECT_IS_VALID(obj));
+
+ if (withlock == CL_FALSE)
+ pthread_mutex_lock(&obj->mutex);
+
+ assert(pthread_equal(pthread_self(), obj->owner) || pthread_equal(obj->owner, invalid_thread_id));
+ obj->owner = invalid_thread_id;
+ pthread_cond_broadcast(&obj->cond);
+
+ if (withlock == CL_FALSE)
+ pthread_mutex_unlock(&obj->mutex);
+}
+
+LOCAL void
+cl_object_wait_on_cond(cl_base_object obj)
+{
+ assert(CL_OBJECT_IS_VALID(obj));
+ pthread_cond_wait(&obj->cond, &obj->mutex);
+}
+
+LOCAL void
+cl_object_notify_cond(cl_base_object obj)
+{
+ assert(CL_OBJECT_IS_VALID(obj));
+ pthread_cond_broadcast(&obj->cond);
+}
+
+/* Need to take all ownership at once, avoid dead lock */
+LOCAL cl_int
+cl_object_take_multi_ownership(cl_base_object *obj, cl_int obj_num, cl_int wait)
+{
+ cl_int i, j;
+ cl_int *ownships = CL_CALLOC(obj_num, sizeof(cl_int));
+ assert(ownships);
+
+ while (1) {
+ for (i = 0; i < obj_num; i++) {
+ ownships[i] = cl_object_take_ownership(obj[i], 0, CL_FALSE);
+ if (ownships[i] == 0)
+ break;
+ }
+
+ if (i == obj_num) { // All get
+ CL_FREE(ownships);
+ return 1;
+ } else {
+ if (wait == 0) {
+ CL_FREE(ownships);
+ return 0;
+ }
+
+ for (j = 0; j < obj_num; j++) {
+ if (ownships[j] == 1) { // Release and do it again
+ cl_object_release_ownership(obj[j], CL_FALSE);
+ ownships[j] = 0;
+ }
+ }
+
+ assert(i < obj_num);
+ // Wait on the one failed
+ cl_object_take_ownership(obj[i], 1, CL_FALSE);
+ ownships[i] = 1;
+ }
+ }
+}
diff --git a/runtime/cl_base_object.h b/runtime/cl_base_object.h
new file mode 100644
index 0000000..da6876f
--- /dev/null
+++ b/runtime/cl_base_object.h
@@ -0,0 +1,85 @@
+/*
+ * 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_BASE_OBJECT_H__
+#define __CL_BASE_OBJECT_H__
+
+#include "cl_utils.h"
+#include "cl_khr_icd.h"
+#include "CL/cl.h"
+#include <pthread.h>
+#include <assert.h>
+
+/************************************************************************
+ Every CL objects should have:
+ ICD dispatcher: Hold the ICD function table pointer.
+
+ Reference: To maintain its' life time. CL retain/release API will
+ change its value. We will destroy the object when the count reach 0.
+
+ Magic: Just a number to represent each CL object. We will use it
+ to check whether it is the object we want.
+
+ Mutex & Cond: Used to protect the CL objects MT safe. lock/unlock
+ critical region should be short enough and should not have any block
+ function call. take_ownership/release_ownership can own the object
+ for a long time. take_ownership will not hold the lock and so will
+ not cause deadlock problems. we can wait on the cond to get the
+ ownership.
+*************************************************************************/
+
+typedef struct _cl_base_object {
+ DEFINE_ICD(dispatch); /* Dispatch function table for icd */
+ cl_ulong magic; /* Magic number for each CL object */
+ atomic_t ref; /* Reference for each CL object */
+ list_node node; /* CL object node belong to some container */
+ pthread_mutex_t mutex; /* THe mutex to protect this object MT safe */
+ pthread_cond_t cond; /* Condition to wait for getting the object */
+ pthread_t owner; /* The thread which own this object */
+} _cl_base_object;
+
+typedef struct _cl_base_object *cl_base_object;
+
+#define CL_OBJECT_INVALID_MAGIC 0xFEFEFEFEFEFEFEFELL
+#define CL_OBJECT_IS_VALID(obj) (((cl_base_object)obj)->magic != CL_OBJECT_INVALID_MAGIC)
+
+#define CL_OBJECT_INC_REF(obj) (atomic_inc(&((cl_base_object)obj)->ref))
+#define CL_OBJECT_DEC_REF(obj) (atomic_dec(&((cl_base_object)obj)->ref))
+#define CL_OBJECT_GET_REF(obj) (atomic_read(&((cl_base_object)obj)->ref))
+
+#define CL_OBJECT_LOCK(obj) (pthread_mutex_lock(&((cl_base_object)obj)->mutex))
+#define CL_OBJECT_UNLOCK(obj) (pthread_mutex_unlock(&((cl_base_object)obj)->mutex))
+
+extern void cl_object_init_base(cl_base_object obj, cl_ulong magic);
+extern void cl_object_destroy_base(cl_base_object obj);
+extern cl_int cl_object_take_ownership(cl_base_object obj, cl_int wait, cl_bool withlock);
+extern void cl_object_release_ownership(cl_base_object obj, cl_bool withlock);
+extern void cl_object_wait_on_cond(cl_base_object obj);
+extern void cl_object_notify_cond(cl_base_object obj);
+extern cl_int cl_object_take_multi_ownership(cl_base_object *obj, cl_int obj_num, cl_int wait);
+
+#define CL_OBJECT_INIT_BASE(obj, magic) (cl_object_init_base((cl_base_object)obj, magic))
+#define CL_OBJECT_DESTROY_BASE(obj) (cl_object_destroy_base((cl_base_object)obj))
+#define CL_OBJECT_TAKE_OWNERSHIP(obj, wait) (cl_object_take_ownership((cl_base_object)obj, wait, CL_FALSE))
+#define CL_OBJECT_RELEASE_OWNERSHIP(obj) (cl_object_release_ownership((cl_base_object)obj, CL_FALSE))
+#define CL_OBJECT_TAKE_OWNERSHIP_WITHLOCK(obj, wait) (cl_object_take_ownership((cl_base_object)obj, wait, CL_TRUE))
+#define CL_OBJECT_RELEASE_OWNERSHIP_WITHLOCK(obj) (cl_object_release_ownership((cl_base_object)obj, CL_TRUE))
+#define CL_OBJECT_WAIT_ON_COND(obj) (cl_object_wait_on_cond((cl_base_object)obj))
+#define CL_OBJECT_NOTIFY_COND(obj) (cl_object_notify_cond((cl_base_object)obj))
+
+#endif /* __CL_BASE_OBJECT_H__ */
--
2.7.4
More information about the Beignet
mailing list