diff --git a/src/threadpool.c b/src/threadpool.c index 74ca41682c8b536617d30b593e8215c10b5d86bc..78c90962d3bc6aedb297c8596950a2942c317b1e 100644 --- a/src/threadpool.c +++ b/src/threadpool.c @@ -26,6 +26,9 @@ #include <math.h> #include <stdlib.h> #include <string.h> +#ifdef SWIFT_DEBUG_THREADPOOL +#include <dlfcn.h> +#endif /* This object's header. */ #include "threadpool.h" @@ -52,6 +55,8 @@ void threadpool_log(struct threadpool *tp, int tid, size_t chunk_size, sizeof(struct mapper_log_entry) * tp->log_size)) == NULL) error("Failed to re-allocate mapper log."); memcpy(new_log, tp->log, sizeof(struct mapper_log_entry) * tp->log_count); + free(tp->log); + tp->log = new_log; } /* Store the new entry. */ @@ -66,6 +71,58 @@ void threadpool_log(struct threadpool *tp, int tid, size_t chunk_size, /* Release the logging mutex. */ pthread_mutex_unlock(&tp->log_mutex); } + +void threadpool_dump_log(struct threadpool *tp, const char *filename, + int reset) { + + /* Open the output file. */ + FILE *fd; + if ((fd = fopen(filename, "w")) == NULL) + error("Failed to create log file '%s'.", filename); + + /* Create a buffer of function names. */ + const int max_names = 100; + struct name_entry { + threadpool_map_function map_function; + const char *name; + }; + struct name_entry names[max_names]; + bzero(names, sizeof(struct name_entry) * max_names); + + /* Write a header. */ + fprintf(fd, "# map_function thread_id chunk_size tic toc\n"); + + /* Loop over the log entries and dump them. */ + for (int i = 0; i < tp->log_count; i++) { + + struct mapper_log_entry *entry = &tp->log[i]; + + /* Look for the function pointer in the buffer. */ + int nid = 0; + while (nid < max_names && names[nid].map_function != entry->map_function) + nid++; + + /* If the name was not found, make a new entry. */ + if (nid == max_names) { + for (int j = 1; j < max_names; j++) names[j - 1] = names[j]; + names[0].map_function = entry->map_function; + Dl_info dl_info; + dladdr(entry->map_function, &dl_info); + names[0].name = dl_info.dli_sname; + nid = 0; + } + + /* Log a line to the file. */ + fprintf(fd, "%s %i %i %lli %lli\n", names[nid].name, entry->tid, + entry->chunk_size, entry->tic, entry->toc); + } + + /* Clear the log if requested. */ + if (reset) tp->log_count = 0; + + /* Close the file. */ + fclose(fd); +} #endif // SWIFT_DEBUG_THREADPOOL void *threadpool_runner(void *data) { @@ -78,7 +135,7 @@ void *threadpool_runner(void *data) { /* Let the controller know that this thread is waiting. */ pthread_mutex_lock(&tp->thread_mutex); -#ifdef SWIFT_DEBUG_THREADPOOL +#ifdef SWIFT_DEBUG_THREADPOOL const int tid = tp->num_threads_waiting; #endif tp->num_threads_waiting += 1; @@ -109,15 +166,15 @@ void *threadpool_runner(void *data) { if (task_ind + chunk_size > tp->map_data_size) chunk_size = tp->map_data_size - task_ind; - /* Call the mapper function. */ - #ifdef SWIFT_DEBUG_THREADPOOL - ticks tic = getticks(); - #endif +/* Call the mapper function. */ +#ifdef SWIFT_DEBUG_THREADPOOL + ticks tic = getticks(); +#endif tp->map_function((char *)tp->map_data + (tp->map_data_stride * task_ind), chunk_size, tp->map_extra_data); - #ifdef SWIFT_DEBUG_THREADPOOL +#ifdef SWIFT_DEBUG_THREADPOOL threadpool_log(tp, tid, chunk_size, tic, getticks()); - #endif +#endif } } } @@ -140,7 +197,7 @@ void threadpool_init(struct threadpool *tp, int num_threads) { /* Init the threadpool mutexes. */ if (pthread_mutex_init(&tp->thread_mutex, NULL) != 0) - error("Failed to initialize mutexex."); + error("Failed to initialize mutex."); if (pthread_cond_init(&tp->control_cond, NULL) != 0 || pthread_cond_init(&tp->thread_cond, NULL) != 0) error("Failed to initialize condition variables."); @@ -155,6 +212,8 @@ void threadpool_init(struct threadpool *tp, int num_threads) { #ifdef SWIFT_DEBUG_THREADPOOL tp->log_size = threadpool_log_initial_size; tp->log_count = 0; + if (pthread_mutex_init(&tp->log_mutex, NULL) != 0) + error("Failed to initialize log mutex."); if ((tp->log = (struct mapper_log_entry *)malloc( sizeof(struct mapper_log_entry) * tp->log_size)) == NULL) error("Failed to allocate mapper log."); @@ -233,15 +292,13 @@ void threadpool_map(struct threadpool *tp, threadpool_map_function map_function, * @brief Re-sets the log for this #threadpool. */ #ifdef SWIFT_DEBUG_THREADPOOL -void threadpool_reset_log(struct threadpool *tp) { - tp->log_count = 0; -} +void threadpool_reset_log(struct threadpool *tp) { tp->log_count = 0; } #endif /** * @brief Frees up the memory allocated for this #threadpool. */ -void threadpool_clean(struct threadpool *tp) { +void threadpool_clean(struct threadpool *tp) { free(tp->threads); #ifdef SWIFT_DEBUG_THREADPOOL free(tp->log); diff --git a/src/threadpool.h b/src/threadpool.h index b817ec5bf8171dabe16ad5c421298739c44408dd..5b3a24ebb261d82b297c6ab832f3450cfe0d9fc8 100644 --- a/src/threadpool.h +++ b/src/threadpool.h @@ -34,22 +34,22 @@ /* Function type for mappings. */ typedef void (*threadpool_map_function)(void *map_data, int num_elements, void *extra_data); - + /* Data for threadpool logging. */ struct mapper_log_entry { /* ID of the thread executing the chunk. */ int tid; - + /* Size of the chunk processed. */ int chunk_size; - + /* Pointer to the mapper function. */ threadpool_map_function map_function; - + /*! Start and end time of this task */ ticks tic, toc; -}; +}; /* Data of a threadpool. */ struct threadpool { @@ -72,17 +72,17 @@ struct threadpool { /* Counter for the number of threads that are done. */ volatile int num_threads_waiting, num_threads_running; - + #ifdef SWIFT_DEBUG_THREADPOOL /* Log of threadpool mapper calls. */ struct mapper_log_entry *log; - + /* Size of the allocated log. */ int log_size; - + /* Number of entries in the log. */ int log_count; - + /* Mutex for log access/reallocation. */ pthread_mutex_t log_mutex; #endif @@ -96,6 +96,8 @@ void threadpool_map(struct threadpool *tp, threadpool_map_function map_function, void threadpool_clean(struct threadpool *tp); #ifdef SWIFT_DEBUG_THREADPOOL void threadpool_reset_log(struct threadpool *tp); +void threadpool_dump_log(struct threadpool *tp, const char *filename, + int reset); #endif #endif /* SWIFT_THREADPOOL_H */