[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