Permalink
Browse files

Implement clCreateContext, clRetainContext and clReleaseContext

Also implemented a test suite for clCreateContext.
  • Loading branch information...
1 parent 50e67f1 commit 3f035837b55910dc0944214806f8bbbae7693e41 @steckdenis committed May 21, 2011
View
1 src/CMakeLists.txt
@@ -23,6 +23,7 @@ set(COAL_SRC_FILES
api/api_gl.cpp
core/cpudevice.cpp
+ core/context.cpp
)
configure_file(builtins/coal-internal.h.in
View
47 src/api/api_context.cpp
@@ -1,22 +1,48 @@
#include <CL/cl.h>
+#include <core/context.h>
// Context APIs
cl_context
clCreateContext(const cl_context_properties *properties,
cl_uint num_devices,
const cl_device_id * devices,
- void (*pfn_notify)(const char *, const void *, size_t, void *),
+ void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *),
void * user_data,
cl_int * errcode_ret)
{
- return 0;
+ cl_int default_errcode_ret;
+
+ // No errcode_ret ?
+ if (!errcode_ret)
+ errcode_ret = &default_errcode_ret;
+
+ if (!devices ||
+ !num_devices ||
+ (!pfn_notify && user_data))
+ {
+ *errcode_ret = CL_INVALID_VALUE;
+ return 0;
+ }
+
+ *errcode_ret = CL_SUCCESS;
+ Coal::Context *ctx = new Coal::Context(properties, num_devices, devices,
+ pfn_notify, user_data, errcode_ret);
+
+ if (*errcode_ret != CL_SUCCESS)
+ {
+ // Initialization failed, destroy context
+ delete ctx;
+ return 0;
+ }
+
+ return (_cl_context *)ctx;
}
cl_context
clCreateContextFromType(const cl_context_properties *properties,
cl_device_type device_type,
- void (*pfn_notify)(const char *, const void *, size_t, void *),
+ void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *),
void * user_data,
cl_int * errcode_ret)
{
@@ -26,13 +52,24 @@ clCreateContextFromType(const cl_context_properties *properties,
cl_int
clRetainContext(cl_context context)
{
- return 0;
+ if (!context)
+ return CL_INVALID_CONTEXT;
+
+ context->reference();
+
+ return CL_SUCCESS;
}
cl_int
clReleaseContext(cl_context context)
{
- return 0;
+ if (!context)
+ return CL_INVALID_CONTEXT;
+
+ if (context->dereference())
+ delete context;
+
+ return CL_SUCCESS;
}
cl_int
View
136 src/core/context.cpp
@@ -0,0 +1,136 @@
+#include "context.h"
+#include "deviceinterface.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+using namespace Coal;
+
+static void default_pfn_notify(const char *, const void *, size_t, void *)
+{
+ return;
+}
+
+Context::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)
+: p_references(1), p_properties(0), p_pfn_notify(pfn_notify),
+ p_user_data(user_data), p_platform(0), p_devices(0)
+{
+ if (!p_pfn_notify)
+ p_pfn_notify = &default_pfn_notify;
+
+ // Explore the properties
+ if (properties)
+ {
+ const unsigned char *props = (const unsigned char *)properties;
+ cl_context_properties prop;
+ size_t props_len = 0;
+
+#define GET_PROP(type, var) \
+ var = *(const type *)props; \
+ props += sizeof(type); \
+ props_len += sizeof(type);
+
+ while (true)
+ {
+ GET_PROP(cl_context_properties, prop)
+
+ if (!prop)
+ break;
+
+ switch (prop)
+ {
+ case CL_CONTEXT_PLATFORM:
+ GET_PROP(cl_platform_id, p_platform);
+ break;
+
+ default:
+ *errcode_ret = CL_INVALID_PROPERTY;
+ return;
+ }
+ }
+
+ // properties may be allocated on the stack of the client application
+ // copy it into a real buffer
+ p_properties = (cl_context_properties *)malloc(props_len);
+
+ if (!p_properties)
+ {
+ *errcode_ret = CL_OUT_OF_HOST_MEMORY;
+ return;
+ }
+
+ memcpy((void *)p_properties, (const void *)properties, props_len);
+ }
+
+ // Verify that the platform is good
+ if (p_platform != 0)
+ {
+ *errcode_ret = CL_INVALID_PLATFORM;
+ return;
+ }
+
+ // Explore the devices
+ p_devices = (DeviceInterface **)malloc(num_devices * sizeof(DeviceInterface *));
+
+ if (!p_devices)
+ {
+ *errcode_ret = CL_OUT_OF_HOST_MEMORY;
+ return;
+ }
+
+ for (int i = 0; i < num_devices; ++i)
+ {
+ cl_device_id device = devices[i];
+
+ if (device == 0)
+ {
+ *errcode_ret = CL_INVALID_DEVICE;
+ return;
+ }
+
+ // Verify that the device is available
+ cl_bool device_available;
+
+ *errcode_ret = device->info(CL_DEVICE_AVAILABLE,
+ sizeof(device_available),
+ &device_available,
+ 0);
+
+ if (errcode_ret != CL_SUCCESS)
+ return;
+
+ if (!device_available)
+ {
+ *errcode_ret = CL_DEVICE_NOT_AVAILABLE;
+ return;
+ }
+
+ // Add the device to the list
+ p_devices[i] = (DeviceInterface *)device;
+ }
+}
+
+Context::~Context()
+{
+ if (p_properties)
+ free((void *)p_properties);
+
+ free((void *)p_devices);
+}
+
+void Context::reference()
+{
+ p_references++;
+}
+
+bool Context::dereference()
+{
+ p_references--;
+ return (p_references == 0);
+}
View
42 src/core/context.h
@@ -0,0 +1,42 @@
+#ifndef __CONTEXT_H__
+#define __CONTEXT_H__
+
+#include <CL/cl.h>
+
+namespace Coal
+{
+
+class DeviceInterface;
+
+class Context
+{
+ public:
+ 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);
+ ~Context();
+
+ void reference();
+ bool dereference(); /*!< @return true if reference becomes 0 */
+
+ private:
+ cl_context_properties *p_properties;
+ void (CL_CALLBACK *p_pfn_notify)(const char *, const void *,
+ size_t, void *);
+ void *p_user_data;
+
+ DeviceInterface **p_devices;
+ unsigned int p_references;
+ cl_platform_id p_platform;
+};
+
+}
+
+struct _cl_context : public Coal::Context
+{};
+
+#endif
View
5 tests/CMakeLists.txt
@@ -5,6 +5,7 @@ set(OPENCL_TESTS_SOURCE
tests.c
test_platform.cpp
test_device.cpp
+ test_context.cpp
)
add_executable(tests ${OPENCL_TESTS_SOURCE})
@@ -14,4 +15,6 @@ MACRO(OPENCL_TEST EXECUTABLE_NAME TEST_NAME)
add_test(${TEST_NAME} ${EXECUTABLE_NAME} ${TEST_NAME})
ENDMACRO(OPENCL_TEST)
-OPENCL_TEST(tests platform device)
+OPENCL_TEST(tests platform)
+OPENCL_TEST(tests device)
+OPENCL_TEST(tests context)
View
99 tests/test_context.cpp
@@ -0,0 +1,99 @@
+#include "test_context.h"
+#include "CL/cl.h"
+
+#include <stdio.h>
+
+START_TEST (test_create_context)
+{
+ cl_platform_id platform = 0;
+ cl_device_id device, wrong_device;
+ cl_int result;
+ cl_context ctx;
+
+ struct __attribute__((packed)) {
+ cl_context_properties prop_platform;
+ cl_platform_id platform;
+ cl_context_properties null;
+ } _properties;
+
+ const cl_context_properties *properties =
+ (const cl_context_properties *)&_properties;
+
+ result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, 0);
+ fail_if(
+ result != CL_SUCCESS,
+ "unable to get a device"
+ );
+
+ _properties.prop_platform = CL_CONTEXT_PLATFORM;
+ _properties.null = 0;
+
+ ctx = clCreateContext(properties, 1, 0, 0, 0, &result);
+ fail_if(
+ result != CL_INVALID_VALUE || ctx != 0,
+ "devices cannot be NULL"
+ );
+
+ ctx = clCreateContext(properties, 0, &device, 0, 0, &result);
+ fail_if(
+ result != CL_INVALID_VALUE || ctx != 0,
+ "num_devices cannot be 0"
+ );
+
+ _properties.platform = (cl_platform_id)1337;
+
+ ctx = clCreateContext(properties, 1, &device, 0, 0, &result);
+ fail_if(
+ result != CL_INVALID_PLATFORM || ctx != 0,
+ "1337 is not a valid platform"
+ );
+
+ _properties.platform = platform;
+ _properties.prop_platform = 1337;
+
+ ctx = clCreateContext(properties, 1, &device, 0, 0, &result);
+ fail_if(
+ result != CL_INVALID_PROPERTY || ctx != 0,
+ "1337 is not a valid cl_context_properties"
+ );
+
+ _properties.prop_platform = CL_CONTEXT_PLATFORM;
+
+ ctx = clCreateContext(properties, 1, &device, 0, (void *)&device, &result);
+ fail_if(
+ result != CL_INVALID_VALUE || ctx != 0,
+ "user_data must be NULL if pfn_notify is NULL"
+ );
+
+ wrong_device = 0;
+
+ ctx = clCreateContext(properties, 1, &wrong_device, 0, 0, &result);
+ fail_if(
+ result != CL_INVALID_DEVICE || ctx != 0,
+ "0 is not a valid device"
+ );
+
+ ctx = clCreateContext(properties, 1, &device, 0, 0, &result);
+ printf("rs : %i, ctx : %p\n", result, ctx);
+ fail_if(
+ result != CL_SUCCESS || ctx == 0,
+ "unable to create a valid context"
+ );
+
+ clReleaseContext(ctx);
+
+ ctx = clCreateContext(properties, 1, &device, 0, 0, 0);
+ fail_if(
+ ctx == 0,
+ "errcode_ret can be NULL"
+ );
+}
+END_TEST
+
+TCase *cl_context_tcase_create(void)
+{
+ TCase *tc = NULL;
+ tc = tcase_create("context");
+ tcase_add_test(tc, test_create_context);
+ return tc;
+}
View
17 tests/test_context.h
@@ -0,0 +1,17 @@
+#ifndef __UTEST_CONTEXT__
+#define __UTEST_CONTEXT__
+
+#include <check.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+TCase *cl_context_tcase_create(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
View
2 tests/test_device.cpp
@@ -1,8 +1,6 @@
#include "test_device.h"
#include "CL/cl.h"
-#include <string.h>
-
START_TEST (test_get_device_ids)
{
cl_platform_id platform = 0;
View
4 tests/test_platform.h
@@ -1,5 +1,5 @@
-#ifndef __UTEST_CONTEXT__
-#define __UTEST_CONTEXT__
+#ifndef __UTEST_PLATFORM__
+#define __UTEST_PLATFORM__
#include <check.h>
View
2 tests/tests.c
@@ -1,5 +1,6 @@
#include "test_platform.h"
#include "test_device.h"
+#include "test_context.h"
#include <stdlib.h>
#include <stdio.h>
@@ -22,6 +23,7 @@ int main(int argc, char **argv)
TESTSUITE(platform, "platform");
TESTSUITE(device, "device");
+ TESTSUITE(context, "context");
if (s == NULL) {
printf("test case %s does not exist", argv[1]);

0 comments on commit 3f03583

Please sign in to comment.