Clover Git
OpenCL 1.1 software implementation

context.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the copyright holder nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00033 #include "context.h"
00034 #include "deviceinterface.h"
00035 #include "propertylist.h"
00036 
00037 #include <cstring>
00038 #include <cstdlib>
00039 
00040 #include <llvm/Target/TargetSelect.h>
00041 
00042 using namespace Coal;
00043 
00044 static void default_pfn_notify(const char *, const void *, size_t, void *)
00045 {
00046     return;
00047 }
00048 
00049 Context::Context(const cl_context_properties *properties,
00050                  cl_uint num_devices,
00051                  const cl_device_id *devices,
00052                  void (CL_CALLBACK *pfn_notify)(const char *, const void *,
00053                                                 size_t, void *),
00054                  void *user_data,
00055                  cl_int *errcode_ret)
00056 : Object(Object::T_Context, 0), p_properties(0), p_pfn_notify(pfn_notify),
00057   p_user_data(user_data), p_devices(0), p_num_devices(0), p_props_len(0),
00058   p_platform(0)
00059 {
00060     if (!p_pfn_notify)
00061         p_pfn_notify = &default_pfn_notify;
00062 
00063     // Intialize LLVM, this can be done more than one time per program
00064     llvm::InitializeNativeTarget();
00065     llvm::InitializeNativeTargetAsmPrinter();
00066 
00067     // Explore the properties
00068     if (properties)
00069     {
00070         const unsigned char *props = (const unsigned char *)properties;
00071         cl_context_properties prop;
00072         size_t props_len = 0;
00073 
00074 #define GET_PROP(type, var)     \
00075     var = *(const type *)props;       \
00076     props += sizeof(type);      \
00077     props_len += sizeof(type);
00078 
00079         while (true)
00080         {
00081             GET_PROP(cl_context_properties, prop)
00082 
00083             if (!prop)
00084                 break;
00085 
00086             switch (prop)
00087             {
00088                 case CL_CONTEXT_PLATFORM:
00089                     GET_PROP(cl_platform_id, p_platform);
00090                     break;
00091 
00092                 default:
00093                     *errcode_ret = CL_INVALID_PROPERTY;
00094                     return;
00095             }
00096         }
00097 
00098         // properties may be allocated on the stack of the client application
00099         // copy it into a real buffer
00100         p_properties = (cl_context_properties *)std::malloc(props_len);
00101         p_props_len = props_len;
00102 
00103         if (!p_properties)
00104         {
00105             *errcode_ret = CL_OUT_OF_HOST_MEMORY;
00106             return;
00107         }
00108 
00109         std::memcpy((void *)p_properties, (const void *)properties, props_len);
00110     }
00111 
00112     // Verify that the platform is good
00113     if (p_platform != 0)
00114     {
00115         *errcode_ret = CL_INVALID_PLATFORM;
00116         return;
00117     }
00118 
00119     // Explore the devices
00120     p_devices = (DeviceInterface **)std::malloc(num_devices * sizeof(DeviceInterface *));
00121     p_num_devices = num_devices;
00122 
00123     if (!p_devices)
00124     {
00125         *errcode_ret = CL_OUT_OF_HOST_MEMORY;
00126         return;
00127     }
00128 
00129     for (cl_uint i=0; i<num_devices; ++i)
00130     {
00131         cl_device_id device = devices[i];
00132 
00133         if (device == 0)
00134         {
00135             *errcode_ret = CL_INVALID_DEVICE;
00136             return;
00137         }
00138 
00139         // Verify that the device is available
00140         cl_bool device_available;
00141 
00142         *errcode_ret = device->info(CL_DEVICE_AVAILABLE,
00143                                     sizeof(device_available),
00144                                     &device_available,
00145                                     0);
00146 
00147         if (*errcode_ret != CL_SUCCESS)
00148             return;
00149 
00150         if (!device_available)
00151         {
00152             *errcode_ret = CL_DEVICE_NOT_AVAILABLE;
00153             return;
00154         }
00155 
00156         // Add the device to the list
00157         p_devices[i] = (DeviceInterface *)device;
00158     }
00159 }
00160 
00161 Context::~Context()
00162 {
00163     if (p_properties)
00164         std::free((void *)p_properties);
00165 
00166     if (p_devices)
00167         std::free((void *)p_devices);
00168 }
00169 
00170 cl_int Context::info(cl_context_info param_name,
00171                      size_t param_value_size,
00172                      void *param_value,
00173                      size_t *param_value_size_ret) const
00174 {
00175     void *value = 0;
00176     size_t value_length = 0;
00177 
00178     union {
00179         cl_uint cl_uint_var;
00180     };
00181 
00182     switch (param_name)
00183     {
00184         case CL_CONTEXT_REFERENCE_COUNT:
00185             SIMPLE_ASSIGN(cl_uint, references());
00186             break;
00187 
00188         case CL_CONTEXT_NUM_DEVICES:
00189             SIMPLE_ASSIGN(cl_uint, p_num_devices);
00190             break;
00191 
00192         case CL_CONTEXT_DEVICES:
00193             MEM_ASSIGN(p_num_devices * sizeof(DeviceInterface *), p_devices);
00194             break;
00195 
00196         case CL_CONTEXT_PROPERTIES:
00197             MEM_ASSIGN(p_props_len, p_properties);
00198             break;
00199 
00200         default:
00201             return CL_INVALID_VALUE;
00202     }
00203 
00204     if (param_value && param_value_size < value_length)
00205         return CL_INVALID_VALUE;
00206 
00207     if (param_value_size_ret)
00208         *param_value_size_ret = value_length;
00209 
00210     if (param_value && value_length /* CONTEXT_PROPERTIES can be of length 0 */)
00211         std::memcpy(param_value, value, value_length);
00212 
00213     return CL_SUCCESS;
00214 }
00215 
00216 bool Context::hasDevice(DeviceInterface *device) const
00217 {
00218     for (unsigned int i=0; i<p_num_devices; ++i)
00219         if (p_devices[i] == device)
00220             return true;
00221 
00222     return false;
00223 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines