/* write content[count] into a temporary file, and return the tempfile name in * output_path */ int pocl_write_tempfile (char *output_path, const char *prefix, const char *suffix, const char *content, uint64_t count, int *ret_fd) { assert (output_path); assert (prefix); assert (suffix); assert (content); assert (count > 0); int fd, err; err = pocl_mk_tempname (output_path, prefix, suffix, &fd); if (err) { POCL_MSG_ERR ("pocl_mk_tempname() failed\n"); return err; } size_t bytes = (size_t)count; ssize_t res; do { res = write (fd, content, bytes); if (res < 0) { POCL_MSG_ERR ("write(%s) failed\n", output_path); return errno; } else { bytes -= res; content += res; } } while (bytes > 0); #ifdef HAVE_FDATASYNC if (fdatasync (fd)) { POCL_MSG_ERR ("fdatasync() failed\n"); return errno; } #elif defined(HAVE_FSYNC) if (fsync (fd)) return errno; #endif err = 0; if (ret_fd) *ret_fd = fd; else { err = close (fd); } return err ? errno : 0; }
int pocl_mk_tempname (char *output, const char *prefix, const char *suffix, int *ret_fd) { #if defined(_MSC_VER) || defined(__MINGW32__) #error "making temporary files on Windows not implemented" #elif defined(HAVE_MKOSTEMPS) || defined(HAVE_MKSTEMPS) || defined(__ANDROID__) /* using mkstemp() instead of tmpnam() has no real benefit * here, as we have to pass the filename to llvm, * but tmpnam() generates an annoying warning... */ int fd; strncpy (output, prefix, POCL_FILENAME_LENGTH); size_t len = strlen (prefix); strncpy (output + len, "_XXXXXX", (POCL_FILENAME_LENGTH - len)); #ifdef __ANDROID__ fd = pocl_mkstemp (output); #else if (suffix) { len += 7; strncpy (output + len, suffix, (POCL_FILENAME_LENGTH - len)); #ifdef HAVE_MKOSTEMPS fd = mkostemps (output, strlen (suffix), O_CLOEXEC); #else fd = mkstemps (output, strlen (suffix)); #endif } else #ifdef HAVE_MKOSTEMPS fd = mkostemp (output, O_CLOEXEC); #else fd = mkstemp (output); #endif #endif if (fd < 0) { POCL_MSG_ERR ("mkstemp() failed\n"); return errno; } int err = 0; if (ret_fd) *ret_fd = fd; else { err = close (fd); } return err ? errno : 0; #else #error mkostemps() / mkstemps() both unavailable #endif }
cl_int program_compile_dynamic_wg_binaries(cl_program program) { unsigned i, device_i; cl_int errcode = CL_SUCCESS; _cl_command_node cmd; assert(program->num_kernels); assert(program->build_status == CL_BUILD_SUCCESS); memset(&cmd, 0, sizeof(_cl_command_node)); cmd.type = CL_COMMAND_NDRANGE_KERNEL; char cachedir[POCL_FILENAME_LENGTH]; cmd.command.run.tmp_dir = cachedir; POCL_LOCK_OBJ(program); /* build the dynamic WG sized parallel.bc and device specific code, * for each kernel & device combo */ for (device_i = 0; device_i < program->num_devices; ++device_i) { cl_device_id device = program->devices[device_i]; /* program may not be built for some of its devices */ if (program->pocl_binaries[device_i] || (!program->binaries[device_i])) continue; cmd.device = device; for (i=0; i < program->num_kernels; i++) { pocl_cache_make_kernel_cachedir_path(cachedir, program, device, program->default_kernels[i], 0,0,0); errcode = pocl_llvm_generate_workgroup_function(device, program->default_kernels[i], 0,0,0); if (errcode != CL_SUCCESS) { POCL_MSG_ERR("Failed to generate workgroup function for " "kernel %s for device %s\n", program->kernel_names[i], device->short_name); goto RET; } cmd.command.run.kernel = program->default_kernels[i]; device->ops->compile_kernel(&cmd, program->default_kernels[i], device); } } RET: POCL_UNLOCK_OBJ(program); return errcode; }
int context_set_properties(cl_context context, const cl_context_properties * properties, cl_int * errcode) { unsigned i; int num_properties = 0; context->properties = NULL; /* verify if data in properties is valid * and set them */ if (properties) { const cl_context_properties *p = properties; const cl_context_properties *q; cl_platform_id platforms[1]; cl_uint num_platforms; cl_bool platform_found; POname(clGetPlatformIDs)(1, platforms, &num_platforms); num_properties = 0; while (p[0] != 0) { /* redefinition of the same property */ for(q=properties; q<p; q+=2) if (q[0] == p[0]) { POCL_MSG_ERR("Duplicate properties: %lu\n", (unsigned long)q[0]); *errcode = CL_INVALID_PROPERTY; return 0; } switch (p[0]) { case CL_CONTEXT_PLATFORM: /* pocl just have one platform */ platform_found = CL_FALSE; for (i=0; i<num_platforms; i++) if ((cl_platform_id)p[1] == platforms[i]) platform_found = CL_TRUE; if (platform_found == CL_FALSE) { POCL_MSG_ERR("Could not find platform %p\n", (void*)p[1]); *errcode = CL_INVALID_PLATFORM; return 0; } p += 2; break; default: POCL_MSG_ERR("Unknown context property: %lu\n", (unsigned long)p[0]); *errcode = CL_INVALID_PROPERTY; return 0; } num_properties++; } context->properties = (cl_context_properties *) malloc ((num_properties * 2 + 1) * sizeof(cl_context_properties)); if (context->properties == NULL) { *errcode = CL_OUT_OF_HOST_MEMORY; return 0; } memcpy(context->properties, properties, (num_properties * 2 + 1) * sizeof(cl_context_properties)); context->num_properties = num_properties; *errcode = 0; return num_properties; } else { context->properties = NULL; context->num_properties = 0; *errcode = 0; return 0; } }
int pocl_write_file(const char *path, const char* content, uint64_t count, int append, int dont_rewrite) { assert(path); assert(content); if (pocl_exists(path)) { if (dont_rewrite) { if (!append) return 0; } else { int res = pocl_remove(path); if (res) { POCL_MSG_ERR ("pocl_remove(%s) failed\n", path); return res; } } } FILE *f; if (append) f = fopen(path, "a"); else f = fopen(path, "w"); if (f == NULL) { POCL_MSG_ERR ("fopen(%s) failed\n", path); return -1; } if (fwrite (content, 1, (size_t)count, f) < (size_t)count) { POCL_MSG_ERR ("fwrite(%s) failed\n", path); return -1; } if (fflush (f)) { POCL_MSG_ERR ("fflush() failed\n"); return errno; } #ifdef HAVE_FDATASYNC if (fdatasync (fileno (f))) { POCL_MSG_ERR ("fdatasync() failed\n"); return errno; } #elif defined(HAVE_FSYNC) if (fsync (fileno (f))) { POCL_MSG_ERR ("fsync() failed\n"); return errno; } #endif return fclose(f); }
int pocl_topology_detect_device_info(cl_device_id device) { hwloc_topology_t pocl_topology; int ret = 0; #ifdef HWLOC_API_2 if (hwloc_get_api_version () < 0x20000) POCL_MSG_ERR ("pocl was compiled against libhwloc 2.x but is" "actually running against libhwloc 1.x \n"); #else if (hwloc_get_api_version () >= 0x20000) POCL_MSG_ERR ("pocl was compiled against libhwloc 1.x but is" "actually running against libhwloc 2.x \n"); #endif /* * hwloc's OpenCL backend causes problems at the initialization stage * because it reloads libpocl.so via the ICD loader. * * See: https://github.com/pocl/pocl/issues/261 * * The only trick to stop hwloc from initializing the OpenCL plugin * I could find is to point the plugin search path to a place where there * are no plugins to be found. */ setenv ("HWLOC_PLUGINS_PATH", "/dev/null", 1); ret = hwloc_topology_init (&pocl_topology); if (ret == -1) { POCL_MSG_ERR ("Cannot initialize the topology.\n"); return ret; } #ifdef HWLOC_API_2 hwloc_topology_set_io_types_filter(pocl_topology, HWLOC_TYPE_FILTER_KEEP_NONE); hwloc_topology_set_type_filter (pocl_topology, HWLOC_OBJ_SYSTEM, HWLOC_TYPE_FILTER_KEEP_NONE); hwloc_topology_set_type_filter (pocl_topology, HWLOC_OBJ_GROUP, HWLOC_TYPE_FILTER_KEEP_NONE); hwloc_topology_set_type_filter (pocl_topology, HWLOC_OBJ_BRIDGE, HWLOC_TYPE_FILTER_KEEP_NONE); hwloc_topology_set_type_filter (pocl_topology, HWLOC_OBJ_MISC, HWLOC_TYPE_FILTER_KEEP_NONE); hwloc_topology_set_type_filter (pocl_topology, HWLOC_OBJ_PCI_DEVICE, HWLOC_TYPE_FILTER_KEEP_NONE); hwloc_topology_set_type_filter (pocl_topology, HWLOC_OBJ_OS_DEVICE, HWLOC_TYPE_FILTER_KEEP_NONE); #else hwloc_topology_ignore_type (pocl_topology, HWLOC_TOPOLOGY_FLAG_WHOLE_IO); hwloc_topology_ignore_type (pocl_topology, HWLOC_OBJ_SYSTEM); hwloc_topology_ignore_type (pocl_topology, HWLOC_OBJ_GROUP); hwloc_topology_ignore_type (pocl_topology, HWLOC_OBJ_BRIDGE); hwloc_topology_ignore_type (pocl_topology, HWLOC_OBJ_MISC); hwloc_topology_ignore_type (pocl_topology, HWLOC_OBJ_PCI_DEVICE); hwloc_topology_ignore_type (pocl_topology, HWLOC_OBJ_OS_DEVICE); #endif ret = hwloc_topology_load (pocl_topology); if (ret == -1) { POCL_MSG_ERR ("Cannot load the topology.\n"); goto exit_destroy; } #ifdef HWLOC_API_2 device->global_mem_size = hwloc_get_root_obj(pocl_topology)->total_memory; #else device->global_mem_size = hwloc_get_root_obj(pocl_topology)->memory.total_memory; #endif // Try to get the number of CPU cores from topology int depth = hwloc_get_type_depth(pocl_topology, HWLOC_OBJ_PU); if(depth != HWLOC_TYPE_DEPTH_UNKNOWN) device->max_compute_units = hwloc_get_nbobjs_by_depth(pocl_topology, depth); /* Find information about global memory cache by looking at the first * cache covering the first PU */ do { size_t cache_size = 0, cacheline_size = 0; hwloc_obj_t core = hwloc_get_next_obj_by_type (pocl_topology, HWLOC_OBJ_CORE, NULL); if (core) { hwloc_obj_t cache = hwloc_get_shared_cache_covering_obj (pocl_topology, core); if ((cache) && (cache->attr)) { cacheline_size = cache->attr->cache.linesize; cache_size = cache->attr->cache.size; } else core = NULL; /* fallback to L1 cache size */ } hwloc_obj_t pu = hwloc_get_next_obj_by_type (pocl_topology, HWLOC_OBJ_PU, NULL); if (!core && pu) { hwloc_obj_t cache = hwloc_get_shared_cache_covering_obj (pocl_topology, pu); if ((cache) && (cache->attr)) { cacheline_size = cache->attr->cache.linesize; cache_size = cache->attr->cache.size; } } if (!cache_size || !cacheline_size) break; device->global_mem_cache_type = 0x2; // CL_READ_WRITE_CACHE, without including all of CL/cl.h device->global_mem_cacheline_size = cacheline_size; device->global_mem_cache_size = cache_size; } while (0); // Destroy topology object and return exit_destroy: hwloc_topology_destroy (pocl_topology); return ret; }