/* * 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 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 . * * Author: Benjamin Segovia */ #include "cl_platform_id.h" #include "cl_device_id.h" #include "cl_genx_driver.h" #include "cl_context.h" #include "cl_command_queue.h" #include "cl_mem.h" #include "cl_alloc.h" #include "cl_utils.h" #include "CL/cl.h" #include #include #include #include /* Do not include the full dependency */ struct intel_driver; /* Get the command buffer interface */ extern struct _drm_intel_bufmgr* intel_driver_get_buf(struct intel_driver*); /* Get the Gen HW version */ extern uint32_t intel_driver_get_ver(struct intel_driver*); static cl_int cl_context_properties_is_ok(const cl_context_properties *properties) { const cl_context_properties *prop = properties; size_t prop_n = 0; cl_int err = CL_SUCCESS; if (properties == NULL) goto exit; while (*prop) { prop += 2; prop_n++; } /* XXX */ FATAL_IF (prop_n > 1, "Only one property is supported now"); INVALID_VALUE_IF (*properties != CL_CONTEXT_PLATFORM); if (UNLIKELY((cl_platform_id) properties[1] != intel_platform)) { err = CL_INVALID_PLATFORM; goto error; } exit: error: return err; } static cl_int cl_device_id_is_ok(const cl_device_id device) { return device != cl_get_gt_device() ? CL_FALSE : CL_TRUE; } LOCAL cl_context cl_create_context(const cl_context_properties * properties, cl_uint num_devices, const cl_device_id * devices, void (CL_CALLBACK * pfn_notify) (const char*, const void*, size_t, void*), void * user_data, cl_int * errcode_ret) { /* cl_platform_id platform = NULL; */ cl_context ctx = NULL; cl_int err = CL_SUCCESS; /* Assert parameters correctness */ INVALID_VALUE_IF (devices == NULL); INVALID_VALUE_IF (num_devices == 0); INVALID_VALUE_IF (pfn_notify == NULL && user_data != NULL); /* XXX */ FATAL_IF (pfn_notify != NULL || user_data != NULL, "Unsupported call back"); FATAL_IF (num_devices != 1, "Only one device is supported"); /* Check that we are getting the right platform */ if (UNLIKELY((err = cl_context_properties_is_ok(properties)) != CL_SUCCESS)) goto error; /* platform = intel_platform; */ /* Now check if the user is asking for the right device */ if (UNLIKELY(cl_device_id_is_ok(*devices) == CL_FALSE)) { err = CL_INVALID_DEVICE; goto error; } /* We are good */ if (UNLIKELY((ctx = cl_context_new()) == NULL)) { err = CL_OUT_OF_HOST_MEMORY; goto error; } /* Attach the device to the context */ ctx->device = *devices; exit: if (errcode_ret != NULL) *errcode_ret = err; return ctx; error: cl_context_delete(ctx); ctx = NULL; goto exit; } LOCAL cl_context cl_context_new(void) { cl_context ctx = NULL; TRY_ALLOC_NO_ERR (ctx, CALLOC(struct _cl_context)); TRY_ALLOC_NO_ERR (ctx->intel_drv, cl_intel_driver_new()); ctx->magic = CL_MAGIC_CONTEXT_HEADER; ctx->ref_n = 1; ctx->ver = intel_driver_get_ver(ctx->intel_drv); pthread_mutex_init(&ctx->program_lock, NULL); pthread_mutex_init(&ctx->queue_lock, NULL); pthread_mutex_init(&ctx->buffer_lock, NULL); pthread_mutex_init(&ctx->sampler_lock, NULL); exit: return ctx; error: cl_context_delete(ctx); ctx = NULL; goto exit; } LOCAL void cl_context_delete(cl_context ctx) { if (UNLIKELY(ctx == NULL)) return; /* We are not done yet */ if (atomic_dec(&ctx->ref_n) > 1) return; /* All object lists should have been freed. Otherwise, the reference counter * of the context cannot be 0 */ assert(ctx->queues == NULL); assert(ctx->programs == NULL); assert(ctx->buffers == NULL); assert(ctx->intel_drv); cl_intel_driver_delete(ctx->intel_drv); ctx->magic = CL_MAGIC_DEAD_HEADER; /* For safety */ cl_free(ctx); } LOCAL void cl_context_add_ref(cl_context ctx) { assert(ctx); atomic_inc(&ctx->ref_n); } LOCAL cl_command_queue cl_context_create_queue(cl_context ctx, cl_device_id device, cl_command_queue_properties properties, /* XXX */ cl_int *errcode_ret) { cl_command_queue queue = NULL; cl_int err = CL_SUCCESS; if (UNLIKELY(device != ctx->device)) { err = CL_INVALID_DEVICE; goto error; } /* We create the command queue and store it in the context list of queues */ TRY_ALLOC (queue, cl_command_queue_new(ctx)); exit: if (errcode_ret) *errcode_ret = err; return queue; error: cl_command_queue_delete(queue); goto exit; } struct _drm_intel_bufmgr* cl_context_get_intel_bufmgr(cl_context ctx) { return intel_driver_get_buf((struct intel_driver*) ctx->intel_drv); }