#include "threadlib.h" int __max_threads; unsigned char isThreadMasterRunning = 0; thread *listT = NULL; thread_master_param_t *param = NULL; pthread_t thread_master; static pthread_mutex_t mutex; void __thread_mutex_init__(pthread_mutex_t *mutex) { if (pthread_mutex_init(mutex, NULL) != 0) { fprintf(stderr, "Thread Master - Error: Failed to initialize mutex.\n"); exit(EXIT_FAILURE); } } void thread_mutex_init(pthread_mutex_t *mutex) { __thread_mutex_init__(mutex); } void __thread_mutex_destroy__(pthread_mutex_t *mutex) { if (pthread_mutex_destroy(mutex) != 0) { fprintf(stderr, "Thread Master - Error: Failed to destroy mutex.\n"); exit(EXIT_FAILURE); } } void thread_mutex_destroy(pthread_mutex_t *mutex) { __thread_mutex_destroy__(mutex); } void *__thread_master_init__(void *params) { thread_master_param_t *param = (thread_master_param_t *)params; listT = (thread *)malloc(param->max_threads * sizeof(thread)); if (listT == NULL) { fprintf(stderr, "Thread Master - Error: Failed to allocate memory for thread pool.\n"); return NULL; } thread_mutex_init(&mutex); __max_threads = param->max_threads; for (int i = 0; i < param->max_threads; i++) { listT[i].worker_param.thread_id = i + 1; listT[i].worker_param.mutex = &mutex; listT[i].worker_param.status = IDLE; listT[i].worker_param.custom_params = param->custom_params; } printf("Thread Master - Success: Ready.\n"); thread_master_assign_new_job(param->__thread_worker__, param->custom_params); return NULL; } void thread_master_init(int max_threads, void *(*__thread_worker__)(void *), void *custom_params) { param = (thread_master_param_t *)malloc(sizeof(thread_master_param_t)); param->max_threads = max_threads; param->__thread_worker__ = __thread_worker__; param->mutex = mutex; param->custom_params = custom_params; static pthread_mutex_t mutex; __thread_mutex_init__(&mutex); param->mutex = mutex; if (pthread_create(&thread_master, NULL, __thread_master_init__, (void *)param) != 0) { fprintf(stderr, "Thread Master - Error: Failed to create thread master.\n"); exit(EXIT_FAILURE); } isThreadMasterRunning = 1; pthread_detach(thread_master); printf("Thread Master - Created\n"); } void thread_master_assign_new_job(void *(*__thread_worker__)(void *), void *custom_params) { for (int i = 0; i < __max_threads; i++) { if (listT[i].worker_param.status == IDLE) { listT[i].worker_param.status = BUSY; listT[i].worker_param.custom_params = custom_params; pthread_create(&(listT[i].thread), NULL, __thread_worker__, &(listT[i].worker_param)); break; } if (i == __max_threads - 1) { sleep_ms(10); i = 0; } } } void thread_master_get_status() { printf("\n\nSTATUS\n"); do { #ifdef DEBUG printf("Thread Master - Waiting for status\n"); printf("Thread Master - Max Threads: %d\n", __max_threads); printf("Param: %d\n", param->max_threads); #endif // DEBUG sleep_ms(100); } while (__max_threads == 0); pthread_mutex_lock(¶m->mutex); for (int i = 0; i < __max_threads; i++) { switch (listT[i].worker_param.status) { case IDLE: printf("Thread %d - IDLE\n", listT[i].worker_param.thread_id); break; case BUSY: printf("Thread %d - BUSY\n", listT[i].worker_param.thread_id); isThreadMasterRunning = 1; break; default: printf("Thread %d - UNKNOWN\n", listT[i].worker_param.thread_id); break; } } pthread_mutex_unlock(¶m->mutex); printf("END STATUS\n"); } void thread_master_free() { while (isThreadMasterRunning) { #ifdef DEBUG printf("Thread Master - Waiting for workers to finish\n"); #endif // DEBUG for (int i = 0; i < __max_threads; i++) { // check if all threads are IDLE if (listT[i].worker_param.status == BUSY) { break; } if (i == __max_threads - 1) { isThreadMasterRunning = 0; } } sleep_ms(100); } __thread_mutex_destroy__(¶m->mutex); free(param); free(listT); printf("Thread Master - Free and Stopped\n"); }