static T get_something(cl_platform_id platform, cl_device_id device, T Slot::*member, thread_scoped_lock &slot_locker) { assert(platform != NULL); OpenCLCache &self = global_instance(); thread_scoped_lock cache_lock(self.cache_lock); pair<CacheMap::iterator,bool> ins = self.cache.insert( CacheMap::value_type(PlatformDevicePair(platform, device), Slot())); Slot &slot = ins.first->second; /* create slot lock only while holding cache lock */ if(!slot.mutex) slot.mutex = new thread_mutex; /* need to unlock cache before locking slot, to allow store to complete */ cache_lock.unlock(); /* lock the slot */ slot_locker = thread_scoped_lock(*slot.mutex); /* If the thing isn't cached */ if(slot.*member == NULL) { /* return with the caller's lock holder holding the slot lock */ return NULL; } /* the item was already cached, release the slot lock */ slot_locker.unlock(); return slot.*member; }
void OpenCLCache::store_context(cl_platform_id platform, cl_device_id device, cl_context context, thread_scoped_lock& slot_locker) { assert(platform != NULL); assert(device != NULL); assert(context != NULL); OpenCLCache &self = global_instance(); thread_scoped_lock cache_lock(self.cache_lock); CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device)); cache_lock.unlock(); Slot &slot = i->second; /* sanity check */ assert(i != self.cache.end()); assert(slot.context == NULL); slot.context = context; /* unlock the slot */ slot_locker.unlock(); /* increment reference count in OpenCL. * The caller is going to release the object when done with it. */ cl_int ciErr = clRetainContext(context); assert(ciErr == CL_SUCCESS); (void)ciErr; }
cl_program OpenCLCache::get_program(cl_platform_id platform, cl_device_id device, ustring key, thread_scoped_lock& slot_locker) { assert(platform != NULL); OpenCLCache& self = global_instance(); thread_scoped_lock cache_lock(self.cache_lock); pair<CacheMap::iterator,bool> ins = self.cache.insert( CacheMap::value_type(PlatformDevicePair(platform, device), Slot())); Slot &slot = ins.first->second; pair<Slot::EntryMap::iterator,bool> ins2 = slot.programs.insert( Slot::EntryMap::value_type(key, Slot::ProgramEntry())); Slot::ProgramEntry &entry = ins2.first->second; /* create slot lock only while holding cache lock */ if(!entry.mutex) entry.mutex = new thread_mutex; /* need to unlock cache before locking slot, to allow store to complete */ cache_lock.unlock(); /* lock the slot */ slot_locker = thread_scoped_lock(*entry.mutex); /* If the thing isn't cached */ if(entry.program == NULL) { /* return with the caller's lock holder holding the slot lock */ return NULL; } /* the item was already cached, release the slot lock */ slot_locker.unlock(); cl_int ciErr = clRetainProgram(entry.program); assert(ciErr == CL_SUCCESS); (void)ciErr; return entry.program; }
void OpenCLCache::store_program(cl_platform_id platform, cl_device_id device, cl_program program, ustring key, thread_scoped_lock& slot_locker) { assert(platform != NULL); assert(device != NULL); assert(program != NULL); OpenCLCache &self = global_instance(); thread_scoped_lock cache_lock(self.cache_lock); CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device)); assert(i != self.cache.end()); Slot &slot = i->second; Slot::EntryMap::iterator i2 = slot.programs.find(key); assert(i2 != slot.programs.end()); Slot::ProgramEntry &entry = i2->second; assert(entry.program == NULL); cache_lock.unlock(); entry.program = program; /* unlock the slot */ slot_locker.unlock(); /* Increment reference count in OpenCL. * The caller is going to release the object when done with it. */ cl_int ciErr = clRetainProgram(program); assert(ciErr == CL_SUCCESS); (void)ciErr; }
static void store_something(cl_platform_id platform, cl_device_id device, T thing, T Slot::*member, thread_scoped_lock &slot_locker) { assert(platform != NULL); assert(device != NULL); assert(thing != NULL); OpenCLCache &self = global_instance(); thread_scoped_lock cache_lock(self.cache_lock); CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device)); cache_lock.unlock(); Slot &slot = i->second; /* sanity check */ assert(i != self.cache.end()); assert(slot.*member == NULL); slot.*member = thing; /* unlock the slot */ slot_locker.unlock(); }
/* note that the lock must be already acquired upon entry. * This is necessary because the caller often peeks at * the header and delegates control to here when it doesn't * specifically handle the current RPC. * The lock must be unlocked before returning */ void process(RPCReceive& rcv, thread_scoped_lock &lock) { if(rcv.name == "mem_alloc") { MemoryType type; network_device_memory mem; device_ptr client_pointer; rcv.read(mem); rcv.read(type); lock.unlock(); client_pointer = mem.device_pointer; /* create a memory buffer for the device buffer */ size_t data_size = mem.memory_size(); DataVector &data_v = data_vector_insert(client_pointer, data_size); if(data_size) mem.data_pointer = (device_ptr)&(data_v[0]); else mem.data_pointer = 0; /* perform the allocation on the actual device */ device->mem_alloc(mem, type); /* store a mapping to/from client_pointer and real device pointer */ pointer_mapping_insert(client_pointer, mem.device_pointer); } else if(rcv.name == "mem_copy_to") { network_device_memory mem; rcv.read(mem); lock.unlock(); device_ptr client_pointer = mem.device_pointer; DataVector &data_v = data_vector_find(client_pointer); size_t data_size = mem.memory_size(); /* get pointer to memory buffer for device buffer */ mem.data_pointer = (device_ptr)&data_v[0]; /* copy data from network into memory buffer */ rcv.read_buffer((uint8_t*)mem.data_pointer, data_size); /* translate the client pointer to a real device pointer */ mem.device_pointer = device_ptr_from_client_pointer(client_pointer); /* copy the data from the memory buffer to the device buffer */ device->mem_copy_to(mem); } else if(rcv.name == "mem_copy_from") { network_device_memory mem; int y, w, h, elem; rcv.read(mem); rcv.read(y); rcv.read(w); rcv.read(h); rcv.read(elem); device_ptr client_pointer = mem.device_pointer; mem.device_pointer = device_ptr_from_client_pointer(client_pointer); DataVector &data_v = data_vector_find(client_pointer); mem.data_pointer = (device_ptr)&(data_v[0]); device->mem_copy_from(mem, y, w, h, elem); size_t data_size = mem.memory_size(); RPCSend snd(socket, &error_func, "mem_copy_from"); snd.write(); snd.write_buffer((uint8_t*)mem.data_pointer, data_size); lock.unlock(); } else if(rcv.name == "mem_zero") { network_device_memory mem; rcv.read(mem); lock.unlock(); device_ptr client_pointer = mem.device_pointer; mem.device_pointer = device_ptr_from_client_pointer(client_pointer); DataVector &data_v = data_vector_find(client_pointer); mem.data_pointer = (device_ptr)&(data_v[0]); device->mem_zero(mem); } else if(rcv.name == "mem_free") { network_device_memory mem; device_ptr client_pointer; rcv.read(mem); lock.unlock(); client_pointer = mem.device_pointer; mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer); device->mem_free(mem); } else if(rcv.name == "const_copy_to") { string name_string; size_t size; rcv.read(name_string); rcv.read(size); vector<char> host_vector(size); rcv.read_buffer(&host_vector[0], size); lock.unlock(); device->const_copy_to(name_string.c_str(), &host_vector[0], size); } else if(rcv.name == "tex_alloc") { network_device_memory mem; string name; InterpolationType interpolation; bool periodic; device_ptr client_pointer; rcv.read(name); rcv.read(mem); rcv.read(interpolation); rcv.read(periodic); lock.unlock(); client_pointer = mem.device_pointer; size_t data_size = mem.memory_size(); DataVector &data_v = data_vector_insert(client_pointer, data_size); if(data_size) mem.data_pointer = (device_ptr)&(data_v[0]); else mem.data_pointer = 0; rcv.read_buffer((uint8_t*)mem.data_pointer, data_size); device->tex_alloc(name.c_str(), mem, interpolation, periodic); pointer_mapping_insert(client_pointer, mem.device_pointer); } else if(rcv.name == "tex_free") { network_device_memory mem; device_ptr client_pointer; rcv.read(mem); lock.unlock(); client_pointer = mem.device_pointer; mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer); device->tex_free(mem); } else if(rcv.name == "load_kernels") { bool experimental; rcv.read(experimental); bool result; result = device->load_kernels(experimental); RPCSend snd(socket, &error_func, "load_kernels"); snd.add(result); snd.write(); lock.unlock(); } else if(rcv.name == "task_add") { DeviceTask task; rcv.read(task); lock.unlock(); if(task.buffer) task.buffer = device_ptr_from_client_pointer(task.buffer); if(task.rgba_half) task.rgba_half = device_ptr_from_client_pointer(task.rgba_half); if(task.rgba_byte) task.rgba_byte = device_ptr_from_client_pointer(task.rgba_byte); if(task.shader_input) task.shader_input = device_ptr_from_client_pointer(task.shader_input); if(task.shader_output) task.shader_output = device_ptr_from_client_pointer(task.shader_output); task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2); task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1); task.update_progress_sample = function_bind(&DeviceServer::task_update_progress_sample, this); task.update_tile_sample = function_bind(&DeviceServer::task_update_tile_sample, this, _1); task.get_cancel = function_bind(&DeviceServer::task_get_cancel, this); device->task_add(task); } else if(rcv.name == "task_wait") { lock.unlock(); blocked_waiting = true; device->task_wait(); blocked_waiting = false; lock.lock(); RPCSend snd(socket, &error_func, "task_wait_done"); snd.write(); lock.unlock(); } else if(rcv.name == "task_cancel") { lock.unlock(); device->task_cancel(); } else if(rcv.name == "acquire_tile") { AcquireEntry entry; entry.name = rcv.name; rcv.read(entry.tile); acquire_queue.push_back(entry); lock.unlock(); } else if(rcv.name == "acquire_tile_none") { AcquireEntry entry; entry.name = rcv.name; acquire_queue.push_back(entry); lock.unlock(); } else if(rcv.name == "release_tile") { AcquireEntry entry; entry.name = rcv.name; acquire_queue.push_back(entry); lock.unlock(); } else { cout << "Error: unexpected RPC receive call \"" + rcv.name + "\"\n"; lock.unlock(); } }