/* There are two scenarios here. One is everything works as it should and second if * the thpool is to be killed. In that manner we try to BYPASS sem_wait and end each thread. */ void thpool_thread_do(thpool_t* tp_p){ while(thpool_keepalive){ if (sem_wait(tp_p->jobqueue->queueSem)) {/* WAITING until there is work in the queue */ perror("thpool_thread_do(): Waiting for semaphore"); exit(1); } if (thpool_keepalive){ /* Read job from queue and execute it */ void*(*func_buff)(void* arg); void* arg_buff; thpool_job_t* job_p; pthread_mutex_lock(&mutex); /* LOCK */ job_p = thpool_jobqueue_peek(tp_p); func_buff=job_p->function; arg_buff =job_p->arg; thpool_jobqueue_removelast(tp_p); pthread_mutex_unlock(&mutex); /* UNLOCK */ func_buff(arg_buff); /* run function */ free(job_p); /* DEALLOC job */ } else { return; /* EXIT thread*/ } } return; }
/* What each thread is doing * * In principle this is an endless loop. The only time this loop gets interuppted is once * thpool_destroy() is invoked or the program exits. * * @param thread thread that will run this function * @return nothing */ static void* thread_do(struct thread* thread_p){ /* Set thread name for profiling and debuging */ char thread_name[128] = {0}; sprintf(thread_name, "thread-pool-%d", thread_p->id); prctl(PR_SET_NAME, thread_name); /* Assure all threads have been created before starting serving */ thpool_* thpool_p = thread_p->thpool_p; /* Register signal handler */ struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = thread_hold; if (sigaction(SIGUSR1, &act, NULL) == -1) { fprintf(stderr, "thread_do(): cannot handle SIGUSR1"); } /* Mark thread as alive (initialized) */ pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_alive += 1; pthread_mutex_unlock(&thpool_p->thcount_lock); while(threads_keepalive){ bsem_wait(thpool_p->jobqueue.has_jobs); if (threads_keepalive){ pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_working++; pthread_mutex_unlock(&thpool_p->thcount_lock); /* Read job from queue and execute it */ void*(*func_buff)(void* arg); void* arg_buff; job* job_p = jobqueue_pull(&thpool_p->jobqueue); if (job_p) { func_buff = job_p->function; arg_buff = job_p->arg; func_buff(arg_buff); free(job_p); } pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_working--; if (!thpool_p->num_threads_working) { pthread_cond_signal(&thpool_p->threads_all_idle); } pthread_mutex_unlock(&thpool_p->thcount_lock); } } pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_alive --; pthread_mutex_unlock(&thpool_p->thcount_lock); return NULL; }
/* What each thread is doing * * In principle this is an endless loop. The only time this loop gets interuppted is once * thpool_destroy() is invoked or the program exits. * * @param thread thread that will run this function * @return nothing */ static void* thread_do(struct thread* thread_p){ /* Assure all threads have been created before starting serving */ thpool_* thpool_p = thread_p->thpool_p; /* Register signal handler */ struct sigaction act; act.sa_handler = thread_hold; if (sigaction(SIGUSR1, &act, NULL) == -1) { fprintf(stderr, "thread_do(): cannot handle SIGUSR1"); } /* Mark thread as alive (initialized) */ pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_alive += 1; pthread_mutex_unlock(&thpool_p->thcount_lock); while(threads_keepalive){ bsem_wait(thpool_p->jobqueue_p->has_jobs); if (threads_keepalive){ pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_working++; pthread_mutex_unlock(&thpool_p->thcount_lock); /* Read job from queue and execute it */ void*(*func_buff)(void* arg); void* arg_buff; job* job_p; pthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex); job_p = jobqueue_pull(thpool_p); pthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex); if (job_p) { func_buff = job_p->function; arg_buff = job_p->arg; func_buff(arg_buff); free(job_p); } pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_working--; pthread_mutex_unlock(&thpool_p->thcount_lock); } } pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_alive --; pthread_mutex_unlock(&thpool_p->thcount_lock); return NULL; }
// roda a fila void poolWheel( piscina* dados ) { do{ //espera ateh que tenha trabalho na fila sem_wait(dados->TarefaFila->filaSemaforo); if ( segura ) { // passa tarefa para fila e executa // Hic Sunt Dracones void *(*func_buff) (void* arg); void* arg_buff; piscina_tarefa* job_p; pthread_mutex_lock( &morfo ); job_p = piscina_fila_peek(dados); if ( job_p == NULL ) { piscina_fila_removelast( dados ); pthread_mutex_unlock( &morfo ); return; } func_buff = job_p->function; arg_buff = job_p->arg; piscina_fila_removelast( dados ); pthread_mutex_unlock( &morfo ); // roda a função func_buff( arg_buff ); if(job_p != NULL) { free( job_p ); job_p=NULL; } segura--; } else { return; } }while ( segura ); return; }
void thpool_thread_do (thpool_t *tp_p){ while (thpool_keepalive) { if (sem_wait (tp_p->jobqueue->queueSem)) //如果工作队列中没有工作,那么所有的线程都将在这里阻塞,当他调用成功的时候,信号量-1 { fprintf(stderr , "Waiting for semaphore\n"); exit (1); } if (thpool_keepalive) { void *(*func_buff) (void *arg); void *arg_buff; thpool_job_t *job_p; pthread_mutex_lock (&mutex); job_p = thpool_jobqueue_peek (tp_p); func_buff = job_p->function ; arg_buff= job_p->arg ; thpool_jobqueue_removelast (tp_p); pthread_mutex_unlock (&mutex); func_buff (arg_buff); free (job_p); } else { return ; } } return ; }
/* What each thread is doing * * In principle this is an endless loop. The only time this loop gets interuppted is once * thpool_destroy() is invoked or the program exits. * * @param thread thread that will run this function * @return nothing */ static void* thread_do(struct thread* thread_p) { /* Set thread name for profiling and debuging */ char thread_name[128] = {0}; sprintf(thread_name, "thread-pool-%d", thread_p->id); #if defined(__linux__) /* Use prctl instead to prevent using _GNU_SOURCE flag and implicit declaration */ prctl(PR_SET_NAME, thread_name); #elif defined(__APPLE__) && defined(__MACH__) pthread_setname_np(thread_name); #else err("thread_do(): pthread_setname_np is not supported on this system"); #endif /* Assure all threads have been created before starting serving */ thpool_* thpool_p = thread_p->thpool_p; /* Register signal handler */ struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = thread_hold; if (sigaction(SIGUSR1, &act, NULL) == -1) { err("thread_do(): cannot handle SIGUSR1"); } /* Mark thread as alive (initialized) */ pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_alive += 1; pthread_mutex_unlock(&thpool_p->thcount_lock); while (threads_keepalive) { bsem_wait(thpool_p->jobqueue.has_jobs); if (threads_keepalive) { pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_working++; pthread_mutex_unlock(&thpool_p->thcount_lock); /* Read job from queue and execute it */ void (*func_buff)(void*); void* arg_buff; job* job_p = jobqueue_pull(&thpool_p->jobqueue); if (job_p) { func_buff = job_p->function; arg_buff = job_p->arg; func_buff(arg_buff); free(job_p); } pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_working--; if (!thpool_p->num_threads_working) { pthread_cond_signal(&thpool_p->threads_all_idle); } pthread_mutex_unlock(&thpool_p->thcount_lock); } } pthread_mutex_lock(&thpool_p->thcount_lock); thpool_p->num_threads_alive --; pthread_mutex_unlock(&thpool_p->thcount_lock); return NULL; }
/* What each thread is doing * * In principle this is an endless loop. The only time this loop gets interrupted is once * thpool_destroy() is invoked or the program exits. * * @param thread thread that will run this function * @return nothing */ static void* thread_do(Thread* thread) { float elapsed; int info; struct timespec cputime; JobQueue* queue; WorkGroup* workGroup; Job* job; thpool_function_type func_buff; void* arg_buff; int i; /* Set thread name for profiling and debugging */ char thread_name[128] = {0}; sprintf(thread_name, "thread-pool-%d", thread->id); #if defined(__linux__) /* Use prctl instead to prevent using _GNU_SOURCE flag and implicit declaration */ prctl(PR_SET_NAME, thread_name); #elif defined(__APPLE__) && defined(__MACH__) pthread_setname_np(thread_name); #else fprintf(stderr, "thread_do(): pthread_setname_np is not supported on this system"); #endif /* Assure all threads have been created before starting serving */ ThPool* thpool = thread->thpool; /* Mark thread as alive (initialized) */ pthread_mutex_lock(&thpool->thcount_lock); thpool->num_threads_alive += 1; pthread_mutex_unlock(&thpool->thcount_lock); queue = thpool->jobqueue; while (thpool->threads_keepalive) { bsem_wait(queue->has_jobs); if (!thpool->threads_keepalive) { break; } pthread_mutex_lock(&thpool->thcount_lock); thpool->num_threads_working++; pthread_mutex_unlock(&thpool->thcount_lock); while (thpool->threads_keepalive) { /* Read job from queue and execute it */ pthread_mutex_lock(&queue->rwmutex); workGroup = jobqueue_pull(thpool, thread->id); pthread_mutex_unlock(&queue->rwmutex); if (workGroup == NULL) break; if (cppadcg_pool_verbose) { get_monotonic_time2(&workGroup->startTime); } for (i = 0; i < workGroup->size; ++i) { job = &workGroup->jobs[i]; if (cppadcg_pool_verbose) { get_monotonic_time2(&job->startTime); } int do_benchmark = job->elapsed != NULL; if (do_benchmark) { elapsed = -get_thread_time(&cputime, &info); } /* Execute the job */ func_buff = job->function; arg_buff = job->arg; func_buff(arg_buff); if (do_benchmark && info == 0) { elapsed += get_thread_time(&cputime, &info); if (info == 0) { (*job->elapsed) = elapsed; } } if (cppadcg_pool_verbose) { get_monotonic_time2(&job->endTime); } } if (cppadcg_pool_verbose) { get_monotonic_time2(&workGroup->endTime); if (thread->processed_groups == NULL) { thread->processed_groups = workGroup; } else { workGroup->prev = thread->processed_groups; thread->processed_groups = workGroup; } } else { free(workGroup->jobs); free(workGroup); } } pthread_mutex_lock(&thpool->thcount_lock); thpool->num_threads_working--; if (!thpool->num_threads_working) { pthread_cond_signal(&thpool->threads_all_idle); } pthread_mutex_unlock(&thpool->thcount_lock); } pthread_mutex_lock(&thpool->thcount_lock); thpool->num_threads_alive--; pthread_mutex_unlock(&thpool->thcount_lock); return NULL; }