One comment. > -----Original Message----- > From: Beignet [mailto:[email protected]] On Behalf Of > [email protected] > Sent: Tuesday, July 19, 2016 19:26 > To: [email protected] > Subject: [Beignet] [PATCH 01/11] Runtime: Add CL base object for all cl > objects. > > From: Junyan He <[email protected]> > > The runtime code is a little verbose in CL object handle. > Every CL objects should have a reference, a lock to protect itself and an ICD > dispatcher. We can organize them to a struct and place it at the beginning of > each CL object. > This base object is also used to protect the CL objects MT safe. > CL_OBJECT_LOCK/CL_OBJECT_UNLOCK macro will lock/unlock objects, but > we should use them within one function call, and the critical region should be > short. > We add CL_OBJECT_TAKE_OWNERSHIP/CL_OBJECT_RELEASE_OWNERSHIP > macro to own the object for a long time. CL_OBJECT_TAKE_OWNERSHIP will > not hold the lock and so will not cause deadlock problems. > For example, when we call NDRange on some memobj, we should take the > ownship of the memobj. If another thread call NDRange on the same > memobj, we should return some error like CL_OUT_OF_RESOURCE to users > and protect the memobj from accessing simultaneously. > > Signed-off-by: Junyan He <[email protected]> > --- > src/CMakeLists.txt | 1 + > src/cl_base_object.c | 102 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > src/cl_base_object.h | 77 +++++++++++++++++++++++++++++++++++++ > 3 files changed, 180 insertions(+) > create mode 100644 src/cl_base_object.c create mode 100644 > src/cl_base_object.h > > diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a002865..cec7cfc > 100644 > --- a/src/CMakeLists.txt > +++ b/src/CMakeLists.txt > @@ -65,6 +65,7 @@ MakeKernelBinStr > ("${CMAKE_CURRENT_SOURCE_DIR}/kernels/" "${BUILT_IN_NAME}") > > set(OPENCL_SRC > ${KERNEL_STR_FILES} > + cl_base_object.c > cl_api.c > cl_alloc.c > cl_kernel.c > diff --git a/src/cl_base_object.c b/src/cl_base_object.c new file mode 100644 > index 0000000..4661977 > --- /dev/null > +++ b/src/cl_base_object.c > @@ -0,0 +1,102 @@ > +/* > + * 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" > + > +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; > +} > + > +LOCAL void > +cl_object_destroy_base(cl_base_object obj) { > + int ref = CL_OBJECT_GET_REF(obj); > + if (ref != 0) { > + DEBUGP(DL_ERROR, "CL object %p, call destroy with a reference %d", obj, > + ref); > + assert(0); > + } > + > + if (!CL_OBJECT_IS_VALID(obj)) { > + DEBUGP(DL_ERROR, > + "CL object %p, call destroy while it is already a dead object", > obj); > + assert(0); > + } > + > + if (obj->owner != invalid_thread_id) { > + DEBUGP(DL_ERROR, "CL object %p, call destroy while still has a > owener %d", > + obj, (int)obj->owner); > + 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) { > + pthread_t self; > + > + assert(CL_OBJECT_IS_VALID(obj)); > + > + self = pthread_self(); > + > + pthread_mutex_lock(&obj->mutex); > + if (pthread_equal(obj->owner, invalid_thread_id)) { > + obj->owner = self; > + pthread_mutex_unlock(&obj->mutex); > + return 1; > + } > + > + if (wait == 0) { > + 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; > + pthread_mutex_unlock(&obj->mutex); > + return 1; > +} > + > +LOCAL void > +cl_object_release_ownership(cl_base_object obj) { > + assert(CL_OBJECT_IS_VALID(obj)); > + > + pthread_mutex_lock(&obj->mutex); > + assert(pthread_equal(pthread_self(), obj->owner)); obj->owner = > + invalid_thread_id; pthread_cond_broadcast(&obj->cond); > + > + pthread_mutex_unlock(&obj->mutex); > +} > diff --git a/src/cl_base_object.h b/src/cl_base_object.h new file mode > 100644 index 0000000..cba4330 > --- /dev/null > +++ b/src/cl_base_object.h > @@ -0,0 +1,77 @@ > +/* > + * 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 */ > + 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_add(&((cl_base_object)obj)- > >ref, > +0))
Is it need using atomic_add to implement CL_OBJECT_GET_REF? I think return ref directly is safe. _______________________________________________ Beignet mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/beignet
