[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