Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Implement clCreateContext, clRetainContext and clReleaseContext

Also implemented a test suite for clCreateContext.
  • Loading branch information...
commit 3f035837b55910dc0944214806f8bbbae7693e41 1 parent 50e67f1
steckdenis authored
1  src/CMakeLists.txt
@@ -23,6 +23,7 @@ set(COAL_SRC_FILES
23 23 api/api_gl.cpp
24 24
25 25 core/cpudevice.cpp
  26 + core/context.cpp
26 27 )
27 28
28 29 configure_file(builtins/coal-internal.h.in
47 src/api/api_context.cpp
... ... @@ -1,4 +1,5 @@
1 1 #include <CL/cl.h>
  2 +#include <core/context.h>
2 3
3 4 // Context APIs
4 5
@@ -6,17 +7,42 @@ cl_context
6 7 clCreateContext(const cl_context_properties *properties,
7 8 cl_uint num_devices,
8 9 const cl_device_id * devices,
9   - void (*pfn_notify)(const char *, const void *, size_t, void *),
  10 + void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *),
10 11 void * user_data,
11 12 cl_int * errcode_ret)
12 13 {
13   - return 0;
  14 + cl_int default_errcode_ret;
  15 +
  16 + // No errcode_ret ?
  17 + if (!errcode_ret)
  18 + errcode_ret = &default_errcode_ret;
  19 +
  20 + if (!devices ||
  21 + !num_devices ||
  22 + (!pfn_notify && user_data))
  23 + {
  24 + *errcode_ret = CL_INVALID_VALUE;
  25 + return 0;
  26 + }
  27 +
  28 + *errcode_ret = CL_SUCCESS;
  29 + Coal::Context *ctx = new Coal::Context(properties, num_devices, devices,
  30 + pfn_notify, user_data, errcode_ret);
  31 +
  32 + if (*errcode_ret != CL_SUCCESS)
  33 + {
  34 + // Initialization failed, destroy context
  35 + delete ctx;
  36 + return 0;
  37 + }
  38 +
  39 + return (_cl_context *)ctx;
14 40 }
15 41
16 42 cl_context
17 43 clCreateContextFromType(const cl_context_properties *properties,
18 44 cl_device_type device_type,
19   - void (*pfn_notify)(const char *, const void *, size_t, void *),
  45 + void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *),
20 46 void * user_data,
21 47 cl_int * errcode_ret)
22 48 {
@@ -26,13 +52,24 @@ clCreateContextFromType(const cl_context_properties *properties,
26 52 cl_int
27 53 clRetainContext(cl_context context)
28 54 {
29   - return 0;
  55 + if (!context)
  56 + return CL_INVALID_CONTEXT;
  57 +
  58 + context->reference();
  59 +
  60 + return CL_SUCCESS;
30 61 }
31 62
32 63 cl_int
33 64 clReleaseContext(cl_context context)
34 65 {
35   - return 0;
  66 + if (!context)
  67 + return CL_INVALID_CONTEXT;
  68 +
  69 + if (context->dereference())
  70 + delete context;
  71 +
  72 + return CL_SUCCESS;
36 73 }
37 74
38 75 cl_int
136 src/core/context.cpp
... ... @@ -0,0 +1,136 @@
  1 +#include "context.h"
  2 +#include "deviceinterface.h"
  3 +
  4 +#include <string.h>
  5 +#include <stdlib.h>
  6 +
  7 +using namespace Coal;
  8 +
  9 +static void default_pfn_notify(const char *, const void *, size_t, void *)
  10 +{
  11 + return;
  12 +}
  13 +
  14 +Context::Context(const cl_context_properties *properties,
  15 + cl_uint num_devices,
  16 + const cl_device_id *devices,
  17 + void (CL_CALLBACK *pfn_notify)(const char *, const void *,
  18 + size_t, void *),
  19 + void *user_data,
  20 + cl_int *errcode_ret)
  21 +: p_references(1), p_properties(0), p_pfn_notify(pfn_notify),
  22 + p_user_data(user_data), p_platform(0), p_devices(0)
  23 +{
  24 + if (!p_pfn_notify)
  25 + p_pfn_notify = &default_pfn_notify;
  26 +
  27 + // Explore the properties
  28 + if (properties)
  29 + {
  30 + const unsigned char *props = (const unsigned char *)properties;
  31 + cl_context_properties prop;
  32 + size_t props_len = 0;
  33 +
  34 +#define GET_PROP(type, var) \
  35 + var = *(const type *)props; \
  36 + props += sizeof(type); \
  37 + props_len += sizeof(type);
  38 +
  39 + while (true)
  40 + {
  41 + GET_PROP(cl_context_properties, prop)
  42 +
  43 + if (!prop)
  44 + break;
  45 +
  46 + switch (prop)
  47 + {
  48 + case CL_CONTEXT_PLATFORM:
  49 + GET_PROP(cl_platform_id, p_platform);
  50 + break;
  51 +
  52 + default:
  53 + *errcode_ret = CL_INVALID_PROPERTY;
  54 + return;
  55 + }
  56 + }
  57 +
  58 + // properties may be allocated on the stack of the client application
  59 + // copy it into a real buffer
  60 + p_properties = (cl_context_properties *)malloc(props_len);
  61 +
  62 + if (!p_properties)
  63 + {
  64 + *errcode_ret = CL_OUT_OF_HOST_MEMORY;
  65 + return;
  66 + }
  67 +
  68 + memcpy((void *)p_properties, (const void *)properties, props_len);
  69 + }
  70 +
  71 + // Verify that the platform is good
  72 + if (p_platform != 0)
  73 + {
  74 + *errcode_ret = CL_INVALID_PLATFORM;
  75 + return;
  76 + }
  77 +
  78 + // Explore the devices
  79 + p_devices = (DeviceInterface **)malloc(num_devices * sizeof(DeviceInterface *));
  80 +
  81 + if (!p_devices)
  82 + {
  83 + *errcode_ret = CL_OUT_OF_HOST_MEMORY;
  84 + return;
  85 + }
  86 +
  87 + for (int i = 0; i < num_devices; ++i)
  88 + {
  89 + cl_device_id device = devices[i];
  90 +
  91 + if (device == 0)
  92 + {
  93 + *errcode_ret = CL_INVALID_DEVICE;
  94 + return;
  95 + }
  96 +
  97 + // Verify that the device is available
  98 + cl_bool device_available;
  99 +
  100 + *errcode_ret = device->info(CL_DEVICE_AVAILABLE,
  101 + sizeof(device_available),
  102 + &device_available,
  103 + 0);
  104 +
  105 + if (errcode_ret != CL_SUCCESS)
  106 + return;
  107 +
  108 + if (!device_available)
  109 + {
  110 + *errcode_ret = CL_DEVICE_NOT_AVAILABLE;
  111 + return;
  112 + }
  113 +
  114 + // Add the device to the list
  115 + p_devices[i] = (DeviceInterface *)device;
  116 + }
  117 +}
  118 +
  119 +Context::~Context()
  120 +{
  121 + if (p_properties)
  122 + free((void *)p_properties);
  123 +
  124 + free((void *)p_devices);
  125 +}
  126 +
  127 +void Context::reference()
  128 +{
  129 + p_references++;
  130 +}
  131 +
  132 +bool Context::dereference()
  133 +{
  134 + p_references--;
  135 + return (p_references == 0);
  136 +}
42 src/core/context.h
... ... @@ -0,0 +1,42 @@
  1 +#ifndef __CONTEXT_H__
  2 +#define __CONTEXT_H__
  3 +
  4 +#include <CL/cl.h>
  5 +
  6 +namespace Coal
  7 +{
  8 +
  9 +class DeviceInterface;
  10 +
  11 +class Context
  12 +{
  13 + public:
  14 + Context(const cl_context_properties *properties,
  15 + cl_uint num_devices,
  16 + const cl_device_id *devices,
  17 + void (CL_CALLBACK *pfn_notify)(const char *, const void *,
  18 + size_t, void *),
  19 + void *user_data,
  20 + cl_int *errcode_ret);
  21 + ~Context();
  22 +
  23 + void reference();
  24 + bool dereference(); /*!< @return true if reference becomes 0 */
  25 +
  26 + private:
  27 + cl_context_properties *p_properties;
  28 + void (CL_CALLBACK *p_pfn_notify)(const char *, const void *,
  29 + size_t, void *);
  30 + void *p_user_data;
  31 +
  32 + DeviceInterface **p_devices;
  33 + unsigned int p_references;
  34 + cl_platform_id p_platform;
  35 +};
  36 +
  37 +}
  38 +
  39 +struct _cl_context : public Coal::Context
  40 +{};
  41 +
  42 +#endif
5 tests/CMakeLists.txt
@@ -5,6 +5,7 @@ set(OPENCL_TESTS_SOURCE
5 5 tests.c
6 6 test_platform.cpp
7 7 test_device.cpp
  8 + test_context.cpp
8 9 )
9 10
10 11 add_executable(tests ${OPENCL_TESTS_SOURCE})
@@ -14,4 +15,6 @@ MACRO(OPENCL_TEST EXECUTABLE_NAME TEST_NAME)
14 15 add_test(${TEST_NAME} ${EXECUTABLE_NAME} ${TEST_NAME})
15 16 ENDMACRO(OPENCL_TEST)
16 17
17   -OPENCL_TEST(tests platform device)
  18 +OPENCL_TEST(tests platform)
  19 +OPENCL_TEST(tests device)
  20 +OPENCL_TEST(tests context)
99 tests/test_context.cpp
... ... @@ -0,0 +1,99 @@
  1 +#include "test_context.h"
  2 +#include "CL/cl.h"
  3 +
  4 +#include <stdio.h>
  5 +
  6 +START_TEST (test_create_context)
  7 +{
  8 + cl_platform_id platform = 0;
  9 + cl_device_id device, wrong_device;
  10 + cl_int result;
  11 + cl_context ctx;
  12 +
  13 + struct __attribute__((packed)) {
  14 + cl_context_properties prop_platform;
  15 + cl_platform_id platform;
  16 + cl_context_properties null;
  17 + } _properties;
  18 +
  19 + const cl_context_properties *properties =
  20 + (const cl_context_properties *)&_properties;
  21 +
  22 + result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, 0);
  23 + fail_if(
  24 + result != CL_SUCCESS,
  25 + "unable to get a device"
  26 + );
  27 +
  28 + _properties.prop_platform = CL_CONTEXT_PLATFORM;
  29 + _properties.null = 0;
  30 +
  31 + ctx = clCreateContext(properties, 1, 0, 0, 0, &result);
  32 + fail_if(
  33 + result != CL_INVALID_VALUE || ctx != 0,
  34 + "devices cannot be NULL"
  35 + );
  36 +
  37 + ctx = clCreateContext(properties, 0, &device, 0, 0, &result);
  38 + fail_if(
  39 + result != CL_INVALID_VALUE || ctx != 0,
  40 + "num_devices cannot be 0"
  41 + );
  42 +
  43 + _properties.platform = (cl_platform_id)1337;
  44 +
  45 + ctx = clCreateContext(properties, 1, &device, 0, 0, &result);
  46 + fail_if(
  47 + result != CL_INVALID_PLATFORM || ctx != 0,
  48 + "1337 is not a valid platform"
  49 + );
  50 +
  51 + _properties.platform = platform;
  52 + _properties.prop_platform = 1337;
  53 +
  54 + ctx = clCreateContext(properties, 1, &device, 0, 0, &result);
  55 + fail_if(
  56 + result != CL_INVALID_PROPERTY || ctx != 0,
  57 + "1337 is not a valid cl_context_properties"
  58 + );
  59 +
  60 + _properties.prop_platform = CL_CONTEXT_PLATFORM;
  61 +
  62 + ctx = clCreateContext(properties, 1, &device, 0, (void *)&device, &result);
  63 + fail_if(
  64 + result != CL_INVALID_VALUE || ctx != 0,
  65 + "user_data must be NULL if pfn_notify is NULL"
  66 + );
  67 +
  68 + wrong_device = 0;
  69 +
  70 + ctx = clCreateContext(properties, 1, &wrong_device, 0, 0, &result);
  71 + fail_if(
  72 + result != CL_INVALID_DEVICE || ctx != 0,
  73 + "0 is not a valid device"
  74 + );
  75 +
  76 + ctx = clCreateContext(properties, 1, &device, 0, 0, &result);
  77 + printf("rs : %i, ctx : %p\n", result, ctx);
  78 + fail_if(
  79 + result != CL_SUCCESS || ctx == 0,
  80 + "unable to create a valid context"
  81 + );
  82 +
  83 + clReleaseContext(ctx);
  84 +
  85 + ctx = clCreateContext(properties, 1, &device, 0, 0, 0);
  86 + fail_if(
  87 + ctx == 0,
  88 + "errcode_ret can be NULL"
  89 + );
  90 +}
  91 +END_TEST
  92 +
  93 +TCase *cl_context_tcase_create(void)
  94 +{
  95 + TCase *tc = NULL;
  96 + tc = tcase_create("context");
  97 + tcase_add_test(tc, test_create_context);
  98 + return tc;
  99 +}
17 tests/test_context.h
... ... @@ -0,0 +1,17 @@
  1 +#ifndef __UTEST_CONTEXT__
  2 +#define __UTEST_CONTEXT__
  3 +
  4 +#include <check.h>
  5 +
  6 +#ifdef __cplusplus
  7 +extern "C" {
  8 +#endif
  9 +
  10 +TCase *cl_context_tcase_create(void);
  11 +
  12 +#ifdef __cplusplus
  13 +}
  14 +#endif
  15 +
  16 +#endif
  17 +
2  tests/test_device.cpp
... ... @@ -1,8 +1,6 @@
1 1 #include "test_device.h"
2 2 #include "CL/cl.h"
3 3
4   -#include <string.h>
5   -
6 4 START_TEST (test_get_device_ids)
7 5 {
8 6 cl_platform_id platform = 0;
4 tests/test_platform.h
... ... @@ -1,5 +1,5 @@
1   -#ifndef __UTEST_CONTEXT__
2   -#define __UTEST_CONTEXT__
  1 +#ifndef __UTEST_PLATFORM__
  2 +#define __UTEST_PLATFORM__
3 3
4 4 #include <check.h>
5 5
2  tests/tests.c
... ... @@ -1,5 +1,6 @@
1 1 #include "test_platform.h"
2 2 #include "test_device.h"
  3 +#include "test_context.h"
3 4
4 5 #include <stdlib.h>
5 6 #include <stdio.h>
@@ -22,6 +23,7 @@ int main(int argc, char **argv)
22 23
23 24 TESTSUITE(platform, "platform");
24 25 TESTSUITE(device, "device");
  26 + TESTSUITE(context, "context");
25 27
26 28 if (s == NULL) {
27 29 printf("test case %s does not exist", argv[1]);

0 comments on commit 3f03583

Please sign in to comment.
Something went wrong with that request. Please try again.