Skip to content

Commit c33b7b1

Browse files
evelikovjaredmauch
andcommitted
tools/depmod: Parallelize module loading
Add pthread-based parallelization to depmod to improve performance on multi-core systems. The changes parallelize: - Module symbol loading Co-authored-by: jared mauch <jared@puck.nether.net> Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
1 parent 179b6c0 commit c33b7b1

2 files changed

Lines changed: 86 additions & 18 deletions

File tree

meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,13 @@ if get_option('tools')
444444
'tools/static-nodes.c',
445445
)
446446

447+
pthread_dep = dependency('threads', required : true)
448+
447449
kmod = executable(
448450
'kmod',
449451
kmod_sources,
450452
link_with : [libshared, libkmod_internal],
453+
dependencies : pthread_dep,
451454
gnu_symbol_visibility : 'hidden',
452455
install : true,
453456
)

tools/depmod.c

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <errno.h>
1212
#include <getopt.h>
1313
#include <limits.h>
14+
#include <pthread.h>
1415
#include <regex.h>
1516
#include <stdio.h>
1617
#include <stdlib.h>
@@ -1597,8 +1598,10 @@ struct module_symbols {
15971598
struct array symbols; /* struct symbol */
15981599
};
15991600

1600-
static int resolve_module_symbols(struct module_symbols *mod_syms)
1601+
static void *resolve_module_symbols(void *arg)
16011602
{
1603+
struct module_symbols *mod_syms = arg;
1604+
16021605
array_init(&mod_syms->symbols, 128);
16031606

16041607
for (size_t i = 0; i < mod_syms->modules_count; i++) {
@@ -1622,14 +1625,14 @@ static int resolve_module_symbols(struct module_symbols *mod_syms)
16221625
mod);
16231626
if (sym == NULL) {
16241627
kmod_module_symbols_free_list(list);
1625-
return -ENOMEM;
1628+
return (void *)(intptr_t)-ENOMEM;
16261629
}
16271630

16281631
err = array_append(&mod_syms->symbols, sym);
16291632
if (err < 0) {
16301633
free(sym);
16311634
kmod_module_symbols_free_list(list);
1632-
return -ENOMEM;
1635+
return (void *)(intptr_t)-ENOMEM;
16331636
}
16341637
}
16351638
kmod_module_symbols_free_list(list);
@@ -1644,54 +1647,116 @@ static int resolve_module_symbols(struct module_symbols *mod_syms)
16441647

16451648
err = array_append(&mod->alias_values, value);
16461649
if (err < 0)
1647-
return err;
1650+
return (void *)(intptr_t)err;
16481651
continue;
16491652
}
16501653
if (streq(key, "softdep")) {
16511654
const char *value = kmod_module_info_get_value(l);
16521655

16531656
err = array_append(&mod->softdep_values, value);
16541657
if (err < 0)
1655-
return err;
1658+
return (void *)(intptr_t)err;
16561659
continue;
16571660
}
16581661
if (streq(key, "weakdep")) {
16591662
const char *value = kmod_module_info_get_value(l);
16601663

16611664
err = array_append(&mod->weakdep_values, value);
16621665
if (err < 0)
1663-
return err;
1666+
return (void *)(intptr_t)err;
16641667
continue;
16651668
}
16661669
}
16671670
kmod_module_get_dependency_symbols(mod->kmod, &mod->dep_sym_list);
16681671
kmod_module_unref(mod->kmod);
16691672
mod->kmod = NULL;
16701673
}
1671-
return 0;
1674+
return (void *)(intptr_t)0;
1675+
}
1676+
1677+
static unsigned int get_cpu_count(void)
1678+
{
1679+
long nproc = sysconf(_SC_NPROCESSORS_ONLN);
1680+
return nproc > 0 ? (unsigned int)nproc : 1;
16721681
}
16731682

16741683
static int depmod_load_modules(struct depmod *depmod)
16751684
{
1676-
struct module_symbols mod_syms = {
1677-
.depmod = depmod,
1678-
.modules = (struct mod **)depmod->modules.array,
1679-
.modules_count = depmod->modules.count,
1680-
};
1685+
struct thread_info {
1686+
pthread_t tid;
1687+
struct module_symbols mod_syms;
1688+
} *tinfo;
1689+
unsigned int n_threads;
1690+
size_t modules_per_thread, last_modules_per_thread;
16811691
int err;
16821692

16831693
DBG("load symbols (%zu modules)\n", depmod->modules.count);
16841694

1685-
err = resolve_module_symbols(&mod_syms);
1686-
if (err < 0)
1695+
n_threads = get_cpu_count();
1696+
if (n_threads > depmod->modules.count)
1697+
n_threads = depmod->modules.count;
1698+
1699+
tinfo = calloc(n_threads, sizeof(*tinfo));
1700+
if (tinfo == NULL)
1701+
return -ENOMEM;
1702+
1703+
modules_per_thread = (depmod->modules.count + n_threads - 1) / n_threads;
1704+
last_modules_per_thread = modules_per_thread - (depmod->modules.count % n_threads);
1705+
1706+
for (unsigned int i = 0; i < n_threads; i++) {
1707+
struct module_symbols *mod_syms = &tinfo[i].mod_syms;
1708+
1709+
mod_syms->depmod = depmod;
1710+
mod_syms->modules =
1711+
(struct mod **)depmod->modules.array + (i * modules_per_thread);
1712+
mod_syms->modules_count = modules_per_thread;
1713+
if (i + 1 == n_threads)
1714+
mod_syms->modules_count = last_modules_per_thread;
1715+
1716+
err = pthread_create(&tinfo[i].tid, NULL, &resolve_module_symbols,
1717+
mod_syms);
1718+
if (err != 0) {
1719+
err = -err; // Most/all pthread API returns positive error
1720+
n_threads = i;
1721+
break;
1722+
}
1723+
}
1724+
1725+
for (unsigned int i = 0; i < n_threads; i++) {
1726+
int local_err;
1727+
void *res;
1728+
1729+
local_err = pthread_join(tinfo[i].tid, &res);
1730+
if (err == 0) {
1731+
if (local_err != 0)
1732+
err = -local_err;
1733+
if ((int)(intptr_t)res != 0)
1734+
err = (int)(intptr_t)res;
1735+
}
1736+
}
1737+
1738+
if (err != 0) {
1739+
for (unsigned int i = 0; i < n_threads; i++) {
1740+
struct module_symbols *mod_syms = &tinfo[i].mod_syms;
1741+
1742+
for (size_t j = 0; j < mod_syms->symbols.count; j++)
1743+
free(mod_syms->symbols.array[j]);
1744+
1745+
array_free_array(&mod_syms->symbols);
1746+
}
1747+
free(tinfo);
16871748
return err;
1749+
}
16881750

1689-
for (size_t i = 0; i < mod_syms.symbols.count; i++) {
1690-
struct symbol *sym = mod_syms.symbols.array[i];
1751+
for (unsigned int i = 0; i < n_threads; i++) {
1752+
struct module_symbols *mod_syms = &tinfo[i].mod_syms;
16911753

1692-
depmod_symbol_add(depmod, sym);
1754+
for (size_t j = 0; j < mod_syms->symbols.count; j++)
1755+
depmod_symbol_add(depmod, mod_syms->symbols.array[j]);
1756+
1757+
array_free_array(&mod_syms->symbols);
16931758
}
1694-
array_free_array(&mod_syms.symbols);
1759+
free(tinfo);
16951760

16961761
DBG("loaded symbols (%zu modules, %u symbols)\n", depmod->modules.count,
16971762
hash_get_count(depmod->symbols));

0 commit comments

Comments
 (0)