Commit 73f2bd88 by Maxime Grégoire

Revert "Replacement of the pthread call by SwiftShader Thread and Resource objects"

This reverts commit 789a9a73. Change-Id: Id1f6732616e407f6a3c9bcafb6c1a0b8e110a2ba Reviewed-on: https://swiftshader-review.googlesource.com/3706Reviewed-by: 's avatarMaxime Grégoire <mgregoire@google.com> Tested-by: 's avatarMaxime Grégoire <mgregoire@google.com>
parent 50ec4359
......@@ -95,7 +95,6 @@
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderFile />
<BrowseInformation>true</BrowseInformation>
<AdditionalIncludeDirectories>../../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
......@@ -119,7 +118,7 @@
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<BrowseInformation>true</BrowseInformation>
<AdditionalIncludeDirectories>../../Common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Users\mgregoire\Documents\Visual Studio 2013\Projects\SwiftCL\pthread\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
......@@ -138,7 +137,6 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OPENCL1_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>../../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
......@@ -163,7 +161,7 @@
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalIncludeDirectories>../../Common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Users\mgregoire\Documents\Visual Studio 2013\Projects\SwiftCL\pthread\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
......@@ -177,10 +175,6 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\Common\CPUID.hpp" />
<ClInclude Include="..\..\Common\Memory.hpp" />
<ClInclude Include="..\..\Common\Resource.hpp" />
<ClInclude Include="..\..\Common\Thread.hpp" />
<ClInclude Include="buffer.h" />
<ClInclude Include="builtins.h" />
<ClInclude Include="cl.h" />
......@@ -205,10 +199,6 @@
<ClInclude Include="worker.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\Common\CPUID.cpp" />
<ClCompile Include="..\..\Common\Memory.cpp" />
<ClCompile Include="..\..\Common\Resource.cpp" />
<ClCompile Include="..\..\Common\Thread.cpp" />
<ClCompile Include="buffer.cpp" />
<ClCompile Include="builtins.cpp" />
<ClCompile Include="commandqueue.cpp" />
......
......@@ -25,8 +25,8 @@ CommandQueue::CommandQueue(Context *ctx,
p_properties(properties), p_flushed(true)
{
// Initialize the locking machinery
p_event_list_mutex = new sw::Resource(0);
p_event_list_cond = new sw::Event();
pthread_mutex_init(&p_event_list_mutex, 0);
pthread_cond_init(&p_event_list_cond, 0);
// Check that the device belongs to the context
if(!ctx->hasDevice(device))
......@@ -41,12 +41,8 @@ CommandQueue::CommandQueue(Context *ctx,
CommandQueue::~CommandQueue()
{
// Free the mutex
p_event_list_mutex->lock(sw::DESTRUCT);
p_event_list_mutex->unlock();
p_event_list_mutex->destruct();
p_event_list_cond->signal();
delete p_event_list_cond;
pthread_mutex_destroy(&p_event_list_mutex);
pthread_cond_destroy(&p_event_list_cond);
}
cl_int CommandQueue::info(cl_command_queue_info param_name,
......@@ -143,12 +139,12 @@ cl_int CommandQueue::checkProperties() const
void CommandQueue::flush()
{
// Wait for the command queue to be in state "flushed".
p_event_list_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_event_list_mutex);
while(!p_flushed)
p_event_list_cond->wait();
pthread_cond_wait(&p_event_list_cond, &p_event_list_mutex);
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
}
void CommandQueue::finish()
......@@ -159,12 +155,12 @@ void CommandQueue::finish()
// All the queued events must have completed. When they are, they get
// deleted from the command queue, so simply wait for it to become empty.
p_event_list_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_event_list_mutex);
while(p_events.size() != 0)
p_event_list_cond->wait();
pthread_cond_wait(&p_event_list_cond, &p_event_list_mutex);
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
}
cl_int CommandQueue::queueEvent(Event *event)
......@@ -177,12 +173,12 @@ cl_int CommandQueue::queueEvent(Event *event)
return rs;
// Append the event at the end of the list
p_event_list_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_event_list_mutex);
p_events.push_back(event);
p_flushed = false;
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
// Timing info if needed
if(p_properties & CL_QUEUE_PROFILING_ENABLE)
......@@ -196,7 +192,7 @@ cl_int CommandQueue::queueEvent(Event *event)
void CommandQueue::cleanEvents()
{
p_event_list_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_event_list_mutex);
std::list<Event *>::iterator it = p_events.begin(), oldit;
......@@ -222,9 +218,9 @@ void CommandQueue::cleanEvents()
// We have cleared the list, so wake up the sleeping threads
if(p_events.size() == 0)
p_event_list_cond->signal();
pthread_cond_broadcast(&p_event_list_cond);
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
// Check now if we have to be deleted
if(references() == 0)
......@@ -233,7 +229,7 @@ void CommandQueue::cleanEvents()
void CommandQueue::pushEventsOnDevice()
{
p_event_list_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_event_list_mutex);
// Explore the events in p_events and push on the device all of them that
// are :
//
......@@ -332,23 +328,23 @@ void CommandQueue::pushEventsOnDevice()
// Set the event as completed. This will call pushEventsOnDevice,
// again, so release the lock to avoid a deadlock. We also return
// because the recursive call will continue our work.
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
event->setStatus(Event::Complete);
return;
}
}
if(p_flushed)
p_event_list_cond->signal();
pthread_cond_broadcast(&p_event_list_cond);
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
}
Event **CommandQueue::events(unsigned int &count)
{
Event **result;
p_event_list_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_event_list_mutex);
count = p_events.size();
result = (Event **)std::malloc(count * sizeof(Event *));
......@@ -369,7 +365,7 @@ Event **CommandQueue::events(unsigned int &count)
// Now result contains an immutable list of events. Even if the events
// become completed in another thread while result is used, the events
// are retained and so guaranteed to remain valid.
p_event_list_mutex->unlock();
pthread_mutex_unlock(&p_event_list_mutex);
return result;
}
......@@ -388,8 +384,8 @@ Event::Event(CommandQueue *parent,
p_status(status), p_device_data(0)
{
// Initialize the locking machinery
p_state_change_cond = new sw::Event();
p_state_mutex = new sw::Resource(0);
pthread_cond_init(&p_state_change_cond, 0);
pthread_mutex_init(&p_state_mutex, 0);
std::memset(&p_timing, 0, sizeof(p_timing));
......@@ -465,13 +461,8 @@ Event::~Event()
if(p_event_wait_list)
std::free((void *)p_event_wait_list);
// Free the mutex
p_state_mutex->lock(sw::DESTRUCT);
p_state_mutex->unlock();
p_state_mutex->destruct();
p_state_change_cond->signal();
delete p_state_change_cond;
pthread_mutex_destroy(&p_state_mutex);
pthread_cond_destroy(&p_state_change_cond);
}
bool Event::isDummy() const
......@@ -495,10 +486,10 @@ bool Event::isDummy() const
void Event::setStatus(Status status)
{
// TODO: If status < 0, terminate all the events depending on us.
p_state_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_state_mutex);
p_status = status;
p_state_change_cond->signal();
pthread_cond_broadcast(&p_state_change_cond);
// Call the callbacks
std::multimap<Status, CallbackData>::const_iterator it;
......@@ -513,7 +504,7 @@ void Event::setStatus(Status status)
data.callback((cl_event)this, p_status, data.user_data);
}
p_state_mutex->unlock();
pthread_mutex_unlock(&p_state_mutex);
// If the event is completed, inform our parent so it can push other events
// to the device.
......@@ -595,12 +586,12 @@ void Event::updateTiming(Timing timing)
if(timing >= Max)
return;
p_state_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_state_mutex);
// Don't update more than one time (NDRangeKernel for example)
if(p_timing[timing])
{
p_state_mutex->unlock();
pthread_mutex_unlock(&p_state_mutex);
return;
}
......@@ -619,7 +610,7 @@ void Event::updateTiming(Timing timing)
p_timing[timing] = rs;
p_state_mutex->unlock();
pthread_mutex_unlock(&p_state_mutex);
}
Event::Status Event::status() const
......@@ -627,25 +618,25 @@ Event::Status Event::status() const
// HACK : We need const qualifier but we also need to lock a mutex
Event *me = (Event *)(void *)this;
me->p_state_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&me->p_state_mutex);
Status ret = p_status;
me->p_state_mutex->unlock();
pthread_mutex_unlock(&me->p_state_mutex);
return ret;
}
void Event::waitForStatus(Status status)
{
p_state_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_state_mutex);
while(p_status != status && p_status > 0)
{
p_state_change_cond->signal();
pthread_cond_wait(&p_state_change_cond, &p_state_mutex);
}
p_state_mutex->unlock();
pthread_mutex_unlock(&p_state_mutex);
}
void *Event::deviceData()
......@@ -668,13 +659,13 @@ void Event::setCallback(cl_int command_exec_callback_type,
data.callback = callback;
data.user_data = user_data;
p_state_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_state_mutex);
p_callbacks.insert(std::pair<Status, CallbackData>(
(Status)command_exec_callback_type,
data));
p_state_mutex->unlock();
pthread_mutex_unlock(&p_state_mutex);
}
cl_int Event::info(cl_event_info param_name,
......
......@@ -5,7 +5,7 @@
#include "object.h"
#include "opencl.h"
#include "Resource.hpp"
#include "pthread.h"
#include <map>
#include <list>
......@@ -148,8 +148,8 @@ namespace Devices
cl_command_queue_properties p_properties;
std::list<Event *> p_events;
sw::Resource *p_event_list_mutex;
sw::Event *p_event_list_cond;
pthread_mutex_t p_event_list_mutex;
pthread_cond_t p_event_list_cond;
bool p_flushed;
};
......@@ -359,8 +359,8 @@ namespace Devices
cl_uint p_num_events_in_wait_list;
const Event **p_event_wait_list;
sw::Event *p_state_change_cond;
sw::Resource *p_state_mutex;
pthread_cond_t p_state_change_cond;
pthread_mutex_t p_state_mutex;
Status p_status;
void *p_device_data;
......
......@@ -6,13 +6,13 @@
#include "program.h"
#include "worker.h"
#include "builtins.h"
#include "propertylist.h"
#include "commandqueue.h"
#include "events.h"
#include "memobject.h"
#include "Thread.hpp"
#include "CPUID.hpp"
#include "kernel.h"
#include "program.h"
#include <cstring>
#include <cstdlib>
......@@ -24,48 +24,84 @@
using namespace Devices;
CPUDevice::CPUDevice()
: DeviceInterface(), p_num_events(0), p_stop(false)
: DeviceInterface(), p_cores(0), p_num_events(0), p_workers(0), p_stop(false),
p_initialized(false)
{
}
void CPUDevice::init()
{
if(p_initialized)
return;
// Initialize the locking machinery
p_event = new sw::Event();
pthread_cond_init(&p_events_cond, 0);
pthread_mutex_init(&p_events_mutex, 0);
//TODO
// Get info about the system
/*p_cores = sysconf(_SC_NPROCESSORS_ONLN);
p_cpu_mhz = 0.0f;
std::filebuf fb;
fb.open("/proc/cpuinfo", std::ios::in);
std::istream is(&fb);
while(!is.eof())
{
std::string key, value;
std::getline(is, key, ':');
is.ignore(1);
std::getline(is, value);
if(key.compare(0, 7, "cpu MHz") == 0)
{
std::istringstream ss(value);
ss >> p_cpu_mhz;
break;
}
}*/
//TODO CHANGE pcore value to real
p_cores = 1;
p_cpu_mhz = 3200;
// Create worker threads
for(unsigned int i = 0; i < sw::CPUID::coreCount(); ++i)
p_workers = (pthread_t *)std::malloc(numCPUs() * sizeof(pthread_t));
for(unsigned int i = 0; i<numCPUs(); ++i)
{
p_workers[i] = new sw::Thread(worker, NULL);
pthread_create(&p_workers[i], 0, &worker, this);
}
eventListResource = new sw::Resource(0);
p_initialized = true;
}
CPUDevice::~CPUDevice()
{
if(!p_initialized)
return;
// Terminate the workers and wait for them
pthread_mutex_lock(&p_events_mutex);
p_stop = true;
for(int thread = 0; thread < sw::CPUID::coreCount(); thread++)
{
if(p_workers[thread])
{
p_workers[thread]->join();
pthread_cond_broadcast(&p_events_cond);
pthread_mutex_unlock(&p_events_mutex);
delete p_workers[thread];
p_workers[thread] = 0;
}
//TODO
for(unsigned int i = 0; i<numCPUs(); ++i)
{
pthread_join(p_workers[i], 0);
}
delete p_event;
eventListResource->lock(sw::DESTRUCT);
eventListResource->unlock();
eventListResource->destruct();
// Free allocated memory
std::free((void *)p_workers);
pthread_mutex_destroy(&p_events_mutex);
p_events_cond = NULL;
//pthread_cond_destroy(&p_events_cond);
}
DeviceBuffer *CPUDevice::createDeviceBuffer(MemObject *buffer, cl_int *rs)
......@@ -167,24 +203,28 @@ void CPUDevice::freeEventDeviceData(Event *event)
void CPUDevice::pushEvent(Event *event)
{
eventListResource->lock(sw::PRIVATE);
// Add an event in the list
pthread_mutex_lock(&p_events_mutex);
p_events.push_back(event);
p_num_events++;
p_num_events++; // Way faster than STL list::size() !
eventListResource->unlock();
pthread_cond_broadcast(&p_events_cond);
pthread_mutex_unlock(&p_events_mutex);
}
Event *CPUDevice::getEvent(bool &stop)
{
eventListResource->lock(sw::PRIVATE);
// Return the first event in the list, if any. Remove it if it is a
// single-shot event.
pthread_mutex_lock(&p_events_mutex);
while(p_num_events == 0 && !p_stop)
pthread_cond_wait(&p_events_cond, &p_events_mutex);
if(p_stop)
{
eventListResource->unlock();
pthread_mutex_unlock(&p_events_mutex);
stop = true;
return 0;
}
......@@ -207,11 +247,16 @@ Event *CPUDevice::getEvent(bool &stop)
p_events.pop_front();
}
eventListResource->unlock();
pthread_mutex_unlock(&p_events_mutex);
return event;
}
unsigned int CPUDevice::numCPUs() const
{
return p_cores;
}
float CPUDevice::cpuMhz() const
{
return p_cpu_mhz;
......@@ -264,7 +309,7 @@ cl_int CPUDevice::info(cl_device_info param_name,
break;
case CL_DEVICE_MAX_COMPUTE_UNITS:
SIMPLE_ASSIGN(cl_uint, sw::CPUID::coreCount());
SIMPLE_ASSIGN(cl_uint, numCPUs());
break;
case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
......
......@@ -4,13 +4,11 @@
#ifndef __CPU_DEVICE_H__
#define __CPU_DEVICE_H__
#define MAX_THREAD_AMOUNT 16
#include <list>
#include "opencl.h"
#include "device_interface.h"
#include "Resource.hpp"
#include "pthread.h"
namespace Devices
{
......@@ -45,16 +43,18 @@ public:
void pushEvent(Event *event);
Event *getEvent(bool &stop);
unsigned int numCPUs() const; /*!< \brief Number of logical CPU cores on the system */
float cpuMhz() const; /*!< \brief Speed of the CPU in Mhz */
private:
unsigned int p_num_events;
unsigned int p_cores, p_num_events;
float p_cpu_mhz;
sw::Thread *p_workers[MAX_THREAD_AMOUNT];
sw::Resource *eventListResource;
pthread_t *p_workers;
std::list<Event *> p_events;
sw::Event *p_event;
bool p_stop;
pthread_cond_t p_events_cond;
pthread_mutex_t p_events_mutex;
bool p_stop, p_initialized;
};
//class GPUDevice : public DeviceInterface
......
// dllmain.cpp : Defines the entry point for the DLL application.
#include "dllmain.h"
#include "windows.h"
#include "opencl.h"
#include "Thread.hpp"
#include "debug.h"
#include <windows.h>
#include <intrin.h>
#include <WinUser.h>
#include "dllmain.h"
#if defined(_WIN32)
typedef DWORD LocalStorageKey;
#else
typedef pthread_key_t LocalStorageKey;
#endif
static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;
static LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;
#if defined(_WIN32)
#define IDD_DIALOG1 101
......
......@@ -28,7 +28,7 @@ CPUKernel::CPUKernel(CPUDevice *device, Kernel *kernel, llvm::Function *function
: DeviceKernel(), p_device(device), p_kernel(kernel), p_function(function),
p_call_function(0)
{
p_call_function_mutex = new sw::Resource(0);
pthread_mutex_init(&p_call_function_mutex, 0);
}
CPUKernel::~CPUKernel()
......@@ -37,9 +37,7 @@ CPUKernel::~CPUKernel()
//if(p_call_function)
//p_call_function->eraseFromParent();
p_call_function_mutex->lock(sw::DESTRUCT);
p_call_function_mutex->unlock();
p_call_function_mutex->destruct();
pthread_mutex_destroy(&p_call_function_mutex);
}
size_t CPUKernel::workGroupSize() const
......@@ -78,7 +76,7 @@ T k_exp(T base, unsigned int e)
size_t CPUKernel::guessWorkGroupSize(cl_uint num_dims, cl_uint dim,
size_t global_work_size) const
{
unsigned int cpus = sw::CPUID::coreCount();
unsigned int cpus = p_device->numCPUs();
// Don't break in too small parts
if(k_exp(global_work_size, num_dims) > 64)
......@@ -150,13 +148,13 @@ size_t CPUKernel::typeOffset(size_t &offset, size_t type_len)
llvm::Function *CPUKernel::callFunction()
{
p_call_function_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_call_function_mutex);
// If we can reuse the same function between work groups, do it
if(p_call_function)
{
llvm::Function *rs = p_call_function;
p_call_function_mutex->unlock();
pthread_mutex_unlock(&p_call_function_mutex);
return rs;
}
......@@ -259,11 +257,11 @@ llvm::Function *CPUKernel::callFunction()
//// Retain the function if it can be reused
//p_call_function = stub_function;
p_call_function_mutex->unlock();
pthread_mutex_unlock(&p_call_function_mutex);
llvm::Function *rs = p_call_function;
p_call_function_mutex->unlock();
pthread_mutex_unlock(&p_call_function_mutex);
return rs;
//return stub_function;
......@@ -277,7 +275,7 @@ CPUKernelEvent::CPUKernelEvent(CPUDevice *device, KernelEvent *event)
p_kernel_args(0)
{
// Mutex
p_mutex = new sw::Resource(0);
pthread_mutex_init(&p_mutex, 0);
// Set current work group to (0, 0, ..., 0)
std::memset(p_current_work_group, 0, event->work_dim() * sizeof(size_t));
......@@ -296,9 +294,7 @@ CPUKernelEvent::CPUKernelEvent(CPUDevice *device, KernelEvent *event)
CPUKernelEvent::~CPUKernelEvent()
{
p_mutex->lock(sw::DESTRUCT);
p_mutex->unlock();
p_mutex->destruct();
pthread_mutex_destroy(&p_mutex);
if(p_kernel_args)
std::free(p_kernel_args);
......@@ -307,7 +303,7 @@ CPUKernelEvent::~CPUKernelEvent()
bool CPUKernelEvent::reserve()
{
// Lock, this will be unlocked in takeInstance()
p_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_mutex);
// Last work group if current == max - 1
return (p_current_wg == p_num_wg - 1);
......@@ -316,23 +312,23 @@ bool CPUKernelEvent::reserve()
bool CPUKernelEvent::finished()
{
bool rs;
p_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_mutex);
rs = (p_finished_wg == p_num_wg);
p_mutex->unlock();
pthread_mutex_unlock(&p_mutex);
return rs;
}
void CPUKernelEvent::workGroupFinished()
{
p_mutex->lock(sw::PRIVATE);
pthread_mutex_lock(&p_mutex);
p_finished_wg++;
p_mutex->unlock();
pthread_mutex_unlock(&p_mutex);
}
CPUKernelWorkGroup *CPUKernelEvent::takeInstance()
......@@ -347,7 +343,7 @@ CPUKernelWorkGroup *CPUKernelEvent::takeInstance()
p_current_wg += 1;
// Release event
p_mutex->unlock();
pthread_mutex_unlock(&p_mutex);
return wg;
}
......
......@@ -2,12 +2,11 @@
#define __CPU_KERNEL_H__
#include "device_interface.h"
#include "CPUID.hpp"
#include "Resource.hpp"
//#include <llvm/ExecutionEngine/GenericValue.h>
#include <vector>
#include <string>
#include "pthread.h"
#include <stdint.h>
......@@ -104,7 +103,7 @@ namespace Devices
CPUDevice *p_device;
Kernel *p_kernel;
llvm::Function *p_function, *p_call_function;
sw::Resource *p_call_function_mutex;
pthread_mutex_t p_call_function_mutex;
};
class CPUKernelEvent;
......@@ -287,7 +286,7 @@ namespace Devices
size_t p_current_work_group[MAX_WORK_DIMS],
p_max_work_groups[MAX_WORK_DIMS];
size_t p_current_wg, p_finished_wg, p_num_wg;
sw::Resource *p_mutex;
pthread_mutex_t p_mutex;
void *p_kernel_args;
};
......
......@@ -17,7 +17,7 @@
using namespace Devices;
void worker(void *data)
void *worker(void *data)
{
CPUDevice *device = (CPUDevice *)data;
bool stop = false;
......@@ -242,4 +242,6 @@ void worker(void *data)
/*if(mapped_data)
munmap(mapped_data, mapped_size);*/
return 0;
}
......@@ -10,6 +10,6 @@
* system. As explained by \ref events , this function waits until there
* are \c Coal::Event objects to process and handle them.
*/
void worker(void *data);
void *worker(void *data);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment