static void * workerLoop(UA_Worker *worker) { UA_Server *server = worker->server; UA_UInt32 *counter = &worker->counter; volatile UA_Boolean *running = &worker->running; /* Initialize the (thread local) random seed with the ram address of worker */ UA_random_seed((uintptr_t)worker); rcu_register_thread(); pthread_mutex_t mutex; // required for the condition variable pthread_mutex_init(&mutex, 0); pthread_mutex_lock(&mutex); while(*running) { struct DispatchJob *dj = (struct DispatchJob*) cds_wfcq_dequeue_blocking(&server->dispatchQueue_head, &server->dispatchQueue_tail); if(dj) { processJob(server, &dj->job); UA_free(dj); } else { /* nothing to do. sleep until a job is dispatched (and wakes up all worker threads) */ pthread_cond_wait(&server->dispatchQueue_condition, &mutex); } uatomic_inc(counter); } pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); UA_ASSERT_RCU_UNLOCKED(); rcu_barrier(); // wait for all scheduled call_rcu work to complete rcu_unregister_thread(); return NULL; }
/** Waits until jobs arrive in the dispatch queue and processes them. */ static void * workerLoop(struct workerStartData *startInfo) { /* Initialized the (thread local) random seed */ UA_random_seed((uintptr_t)startInfo); rcu_register_thread(); UA_UInt32 *c = UA_malloc(sizeof(UA_UInt32)); uatomic_set(c, 0); *startInfo->workerCounter = c; UA_Server *server = startInfo->server; UA_free(startInfo); pthread_mutex_t mutex; // required for the condition variable pthread_mutex_init(&mutex,0); pthread_mutex_lock(&mutex); struct timespec to; while(*server->running) { struct DispatchJobsList *wln = (struct DispatchJobsList*) cds_wfcq_dequeue_blocking(&server->dispatchQueue_head, &server->dispatchQueue_tail); if(wln) { processJobs(server, wln->jobs, wln->jobsSize); UA_free(wln->jobs); UA_free(wln); } else { /* sleep until a work arrives (and wakes up all worker threads) */ #if defined(__APPLE__) || defined(__MACH__) // OS X does not have clock_gettime, use clock_get_time clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); to.tv_sec = mts.tv_sec; to.tv_nsec = mts.tv_nsec; #else clock_gettime(CLOCK_REALTIME, &to); #endif to.tv_sec += 2; pthread_cond_timedwait(&server->dispatchQueue_condition, &mutex, &to); } uatomic_inc(c); // increase the workerCounter; } pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); rcu_barrier(); // wait for all scheduled call_rcu work to complete rcu_unregister_thread(); /* we need to return _something_ for pthreads */ return NULL; }