bugs: certain recent proposals may ignore the relevant problems.
[libale.git] / src / libale.h
blob18082d38445f6b12faa1ed175646e1ae46aa8a39
1 /*
2 * Copyright 2008, 2009 David Hilvert <dhilvert@gmail.com>
4 * This file is part of libale.
6 * libale is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU Affero General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
11 * libale is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
14 * more details.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with libale. If not, see <http://www.gnu.org/licenses/>.
20 #include <ale.h>
22 #include <math.h>
23 #include <stdlib.h>
26 * For now, do nothing with assertions. This is useful for preserving
27 * assertion statements used in code imported from ALE, and may be useful for
28 * emitting debugging messages in the future.
31 #define ale_assert(x) ;
34 * Abstract types used internally by host code (cf. ale_context_get_*_type for
35 * preferred computational types).
38 typedef double ale_pos;
39 typedef double ale_accum;
40 typedef double ale_real;
42 typedef struct { ale_pos x[3]; } point;
44 static point point2(ale_pos x0, ale_pos x1) {
45 point p;
47 p.x[0] = x0;
48 p.x[1] = x1;
49 p.x[2] = 0;
52 static point point3(ale_pos x0, ale_pos x1, ale_pos x2) {
53 point p;
55 p.x[0] = x0;
56 p.x[1] = x1;
57 p.x[2] = x2;
60 static point point_posinf(int dim) {
61 int d;
62 point p;
64 /* Division logic from ALE d2::point::posinf */
66 ale_pos a = +1;
67 ale_pos z = +0;
69 a = a / z;
71 for (d = 0; d < 3; d++)
72 p.x[d] = (d < dim) ? a : 0;
74 return p;
77 static point point_neginf(int dim) {
78 int d;
79 point p = point_posinf(dim);
81 for (d = 0; d < dim && d < 3; d++)
82 p.x[d] = -p.x[d];
84 return p;
87 static int point_defined2(point p) {
88 return (!isnan(p.x[0]) && !isnan(p.x[1]));
91 static int point_defined3(point p) {
92 return (!isnan(p.x[0]) && !isnan(p.x[1]) && !isnan(p.x[2]));
96 * Element of the device memory table.
98 * XXX: this might be better done as a table with struct { ale_context c; cl_mem m[0]; };
101 typedef union {
102 cl_mem memory;
103 ale_context context;
104 } mem_table_entry;
107 * Libale void and file pointer types.
110 ALE_POINTER(void, libale_voidp)
111 ALE_POINTER(FILE, libale_filep)
114 * Get ale_context associated with a table index from an ALE_POINTER to device
115 * memory.
118 static ale_context api_to_ac(mem_table_entry *p) {
121 * Get the slot just prior to an invalid cl_mem (marking the start of
122 * the cl_mem table.
125 while (p->memory != ((cl_mem) 0))
126 p--;
128 p--;
130 return p->context;
134 * Macro for obtaining a pointer from ALE_POINTER type.
137 #define P(x) x.p
140 * Macro for converting (typecasting) index to mem_table_entry.
143 #define LIBALE_INDEX_TO_MEMENTRY(x) ((mem_table_entry *) (((char *) NULL) + x.t.index))
146 * Macro for the reverse (but with bare index).
149 #define LIBALE_MEMENTRY_TO_INDEX(x) ((cl_long) (((char *) x) - ((char *) NULL)))
152 * Macro for obtaining an ale_context associated with an ALE_POINTER to device
153 * memory.
156 #define C(x) api_to_ac(LIBALE_INDEX_TO_MEMENTRY(x))
159 * Macro for obtaining a pointer to host-mapped memory from an ALE_POINTER
160 * type to device memory. We assume Q idempotent over multiple invocations.
161 * We also assume results from Q stale after a kernel execution.
164 #define Q(TYPENAME, x) ((struct _ ## TYPENAME *) ale_context_map(C(x), LIBALE_INDEX_TO_MEMENTRY(x)))
167 * Macro for creating a variable pointer to host-mapped memory via Q().
170 #define DQ(TYPENAME, x, px) struct _ ## TYPENAME *px = Q(TYPENAME, x);
173 * Context interface for mapping, idempotent over multiple invocations.
176 void *ale_context_map(ale_context ac, mem_table_entry *index);
179 * Macro for unmapping a previously mapped ALE_POINTER with P(p) = Q(x). (We
180 * assume that calling this is generally unnecessary, and that the context will
181 * unmap automatically when necessary, such as prior to a kernel execution or
182 * [is this necessary?] prior to freeing of a mementry argument.)
185 #define R(x, p) ale_context_unmap(C(x), LIBALE_INDEX_TO_MEMENTRY(x), P(p))
188 * Context interface for allocating, referencing, and freeing memory table
189 * elements.
192 mem_table_entry *ale_context_malloc(ale_context ac, size_t s);
193 mem_table_entry *ale_context_mref(ale_context ac, cl_mem m);
194 cl_mem ale_context_mretain(ale_context ac, mem_table_entry *e);
195 void ale_context_mrelease(ale_context ac, mem_table_entry *e);
198 * Null macro.
201 #define N(TYPENAME) TYPENAME ## _NULL()
204 * Context interface for unmapping.
207 int ale_context_unmap(ale_context ac, mem_table_entry *index, void *p);
210 * Macros for common API type elements and functions.
214 * We do our own reference counting, both because the CL spec states that
215 * returned reference counts are unsuitable for general uses (although they
216 * would probably be usable here, allowing destruction functionality, by
217 * incrementing reference count by one at the time of object creation), and
218 * also because using our own structure member allows us to reference count in
219 * host memory, or in a sub-allocated portion of a cl_mem object (allowing the
220 * possibility of several Libale objects per cl_mem allocation).
223 #define TYPE_COMMON_ELEMENTS \
224 unsigned int refcount;
226 #define TYPE_STRUCTURE(TYPENAME, TYPE_ELEMENTS) \
227 struct _ ## TYPENAME { \
228 TYPE_COMMON_ELEMENTS \
229 TYPE_ELEMENTS \
232 #define TYPE_HOST_COMMON_FUNCTIONS(TYPENAME, DESTRUCTOR) \
233 int TYPENAME ## _valid(TYPENAME xarg) { \
234 if (P(xarg) == NULL || P(xarg)->refcount == 0) \
235 return 0; \
236 return 1; \
239 TYPENAME TYPENAME ## _NULL() { \
240 TYPENAME result; \
241 P(result) = NULL; \
242 return result; \
245 int TYPENAME ## _retain(TYPENAME xarg) { \
246 if (!TYPENAME ## _valid(xarg)) \
247 return ALE_UNSPECIFIED_FAILURE; \
248 if (!(P(xarg)->refcount + 1 > 0)) \
249 return ALE_UNSPECIFIED_FAILURE; \
250 P(xarg)->refcount++; \
251 return ALE_SUCCESS; \
254 static TYPENAME TYPENAME ## _alloc() { \
255 TYPENAME retval; \
256 P(retval) = (struct _ ## TYPENAME *) malloc(sizeof(struct _ ## TYPENAME)); \
257 if (P(retval)) \
258 P(retval)->refcount = 1; \
259 return retval; \
262 static void TYPENAME ## _free(TYPENAME this) { \
263 DESTRUCTOR \
266 int TYPENAME ## _release(TYPENAME xarg) { \
267 if (!TYPENAME ## _valid(xarg)) \
268 return ALE_UNSPECIFIED_FAILURE; \
269 P(xarg)->refcount--; \
270 if (P(xarg)->refcount == 0) {\
271 TYPENAME ## _free(xarg); \
272 free(P(xarg)); \
274 return ALE_SUCCESS; \
277 #define TYPE_COMMON_FUNCTIONS(TYPENAME, DESTRUCTOR) \
278 int TYPENAME ## _valid(TYPENAME xarg) { \
279 if (xarg.t.index == 0 || Q(TYPENAME, xarg) == NULL || Q(TYPENAME, xarg)->refcount == 0) \
280 return 0; \
281 return 1; \
284 TYPENAME TYPENAME ## _NULL() { \
285 TYPENAME result; \
286 result.t.index = 0; \
287 return result; \
290 int TYPENAME ## _retain(TYPENAME xarg) { \
291 if (!TYPENAME ## _valid(xarg)) \
292 return ALE_UNSPECIFIED_FAILURE; \
293 if (!(Q(TYPENAME, xarg)->refcount + 1 > 0)) \
294 return ALE_UNSPECIFIED_FAILURE; \
295 Q(TYPENAME, xarg)->refcount++; \
296 return ALE_SUCCESS; \
299 static TYPENAME TYPENAME ## _alloc(ale_context ac) { \
300 TYPENAME retval; \
301 mem_table_entry *e = ale_context_malloc(ac, sizeof(struct _ ## TYPENAME)); \
302 retval.t.index = LIBALE_MEMENTRY_TO_INDEX(e); \
303 if (retval.t.index == 0) \
304 return retval; \
305 if (!Q(TYPENAME, retval)) { \
306 ale_context_mrelease(ac, e); \
307 return TYPENAME ## _NULL(); \
309 Q(TYPENAME, retval)->refcount = 1; \
310 return retval; \
313 static void TYPENAME ## _free(TYPENAME this) { \
314 DESTRUCTOR \
317 int TYPENAME ## _release(TYPENAME xarg) { \
318 if (!TYPENAME ## _valid(xarg)) \
319 return ALE_UNSPECIFIED_FAILURE; \
320 Q(TYPENAME, xarg)->refcount--; \
321 if (Q(TYPENAME, xarg)->refcount == 0) {\
322 TYPENAME ## _free(xarg); \
323 ale_context_mrelease(C(xarg), LIBALE_INDEX_TO_MEMENTRY(xarg)); \
325 return ALE_SUCCESS; \
328 #define TYPE_HOST(TYPENAME, TYPE_ELEMENTS, DESTRUCTOR) \
329 TYPE_STRUCTURE(TYPENAME, TYPE_ELEMENTS) \
330 TYPE_HOST_COMMON_FUNCTIONS(TYPENAME, DESTRUCTOR)
332 #define TYPE(TYPENAME, TYPE_ELEMENTS, DESTRUCTOR) \
333 ALE_DATA_TYPE(_ ## TYPENAME ## _def, TYPE_STRUCTURE(TYPENAME, TYPE_ELEMENTS) ) \
334 TYPE_COMMON_FUNCTIONS(TYPENAME, DESTRUCTOR)
337 * Macros for API parameter operations.
340 #define HOST_PARAMETER_R(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
341 PARAMETER_TYPE OBJECT_TYPE ## _get_ ## PARAMETER_NAME (OBJECT_TYPE object) { \
342 if (!OBJECT_TYPE ## _valid(object)) \
343 return ((PARAMETER_TYPE) 0); \
344 return P(object)->PARAMETER_NAME; \
347 #define HOST_PARAMETER_W(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
348 int OBJECT_TYPE ## _set_ ## PARAMETER_NAME (OBJECT_TYPE object, PARAMETER_TYPE value){ \
349 if (!OBJECT_TYPE ## _valid(object)) \
350 return ALE_UNSPECIFIED_FAILURE; \
351 P(object)->PARAMETER_NAME = value; \
352 return ALE_SUCCESS; \
355 #define HOST_PARAMETER_RW(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
356 HOST_PARAMETER_R(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
357 HOST_PARAMETER_W(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE)
359 #define PARAMETER_R(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
360 PARAMETER_TYPE OBJECT_TYPE ## _get_ ## PARAMETER_NAME (OBJECT_TYPE object) { \
361 if (!OBJECT_TYPE ## _valid(object)) \
362 return ((PARAMETER_TYPE) 0); \
363 return Q(OBJECT_TYPE, object)->PARAMETER_NAME; \
366 #define PARAMETER_W(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
367 int OBJECT_TYPE ## _set_ ## PARAMETER_NAME (OBJECT_TYPE object, PARAMETER_TYPE value){ \
368 if (!OBJECT_TYPE ## _valid(object)) \
369 return ALE_UNSPECIFIED_FAILURE; \
370 Q(OBJECT_TYPE, object)->PARAMETER_NAME = value; \
371 return ALE_SUCCESS; \
374 #define PARAMETER_RW(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
375 PARAMETER_R(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE) \
376 PARAMETER_W(OBJECT_TYPE, PARAMETER_NAME, PARAMETER_TYPE)
379 * Detemine type size.
382 static int type_size(int type) {
383 if (type == ALE_TYPE_UINT_8)
384 return 1;
385 if (type == ALE_TYPE_UINT_16)
386 return 2;
387 if (type == ALE_TYPE_FLOAT_32 || type == ALE_TYPE_UINT_32)
388 return 4;
389 if (type == ALE_TYPE_FLOAT_64 || type == ALE_TYPE_UINT_64)
390 return 8;