From: Junyan He <junyan...@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...@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 _______________________________________________ Beignet mailing list Beignet@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/beignet