/*
* 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 .
*
*/
#include
#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;
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) {
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);
}
if (!list_node_out_of_list(&obj->node)) {
DEBUGP(DL_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));
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);
}