diff --git a/Makefile.am b/Makefile.am index 2ee81bd..0dc576c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # . SUBDIRS = tests -AM_CXXFLAGS = -std=c++11 -Wall -Wextra -pedantic +AM_CXXFLAGS = -std=c++11 -Wall -Wextra -pedantic -pthread bin_PROGRAMS = termux-elf-cleaner diff --git a/elf-cleaner.cpp b/elf-cleaner.cpp index 144be0f..e4c6031 100644 --- a/elf-cleaner.cpp +++ b/elf-cleaner.cpp @@ -19,7 +19,10 @@ You should have received a copy of the GNU General Public License along with termux-elf-cleaner. If not, see . */ -#include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include #include #include @@ -29,6 +32,12 @@ along with termux-elf-cleaner. If not, see #include #include +#include +#include +#include +#include +#include + #include "arghandling.h" // Include a local elf.h copy as not all platforms have it. @@ -55,6 +64,8 @@ int api_level = 21; bool dry_run = false; bool quiet = false; +std::mutex mutex; + static char const *const usage_message[] = { "\ \n\ @@ -64,6 +75,7 @@ dynamic section entries which the Android linker warns about.\n\ Options:\n\ \n\ --api-level NN choose target api level, i.e. 21, 24, ..\n\ +--jobs N run parallel on n thread(s).\n\ --dry-run print info but but do not remove entries\n\ --quiet do not print info about removed entries\n\ --help display this help and exit\n\ @@ -299,6 +311,16 @@ int parse_file(const char *file_name) return 0; } +void parse_file_handler(std::deque* files, unsigned int &pos) { + while (files->size() > pos) { + mutex.lock(); + const char *file = files->at(pos); + pos++; + mutex.unlock(); + parse_file(file); + } +} + int main(int argc, char **argv) { int skip_args = 0; @@ -334,9 +356,21 @@ int main(int argc, char **argv) if (argmatch(argv, argc, "-quiet", "--quiet", 3, NULL, &skip_args)) quiet = true; - for (int i = skip_args+1; i < argc; i++) { - if (parse_file(argv[i]) != 0) - return 1; - } + int threads_count = std::thread::hardware_concurrency(); + int files_count = argc - (skip_args + 1); + argmatch(argv, argc, "-jobs", "--jobs", 1, &threads_count, &skip_args); + if (argc - (skip_args + 1) <= threads_count) threads_count = files_count; + if (threads_count < 1) threads_count = 1; + + std::deque files; + std::vector threads(threads_count); + unsigned int pos = 0; + + for (int i = skip_args + 1; i < argc; i++) + files.push_back(argv[i]); + for (int i = 0; i < threads_count; i++) + threads[i] = std::thread(parse_file_handler, &files, std::ref(pos)); + for (std::thread& thread : threads) + if (thread.joinable()) thread.join(); return 0; }