[Beignet] [PATCH 01/11] Runtime: Add CL base object for all cl objects.
Yang, Rong R
rong.r.yang at intel.com
Thu Sep 1 07:50:56 UTC 2016
One comment.
> -----Original Message-----
> From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of
> junyan.he at inbox.com
> Sent: Tuesday, July 19, 2016 19:26
> To: beignet at lists.freedesktop.org
> Subject: [Beignet] [PATCH 01/11] Runtime: Add CL base object for all cl
> objects.
>
> From: Junyan He <junyan.he at intel.com>
>
> 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 <junyan.he at intel.com>
> ---
> 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.
More information about the Beignet
mailing list