summaryrefslogtreecommitdiffstats
path: root/userspace/src/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/src/module.c')
-rw-r--r--userspace/src/module.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/userspace/src/module.c b/userspace/src/module.c
new file mode 100644
index 00000000..c111c6cb
--- /dev/null
+++ b/userspace/src/module.c
@@ -0,0 +1,167 @@
1/*
2 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <errno.h>
24#include <dlfcn.h>
25#include <dirent.h>
26#include <string.h>
27#include <stdlib.h>
28
29#include <sys/types.h>
30
31#include <unit/core.h>
32#include <unit/io.h>
33#include <unit/args.h>
34#include <unit/unit.h>
35
36static int check_module(struct unit_fw *fw, struct unit_module *mod)
37{
38 unsigned int i;
39
40 /*
41 * Make sure this module has reasonable data.
42 */
43 if (mod->name == NULL) {
44 core_err(fw, "Unnamed module!");
45 return -1;
46 }
47
48 if (mod->tests == NULL || mod->nr_tests == 0) {
49 core_err(fw, "%s: Empty module!\n", mod->name);
50 return -1;
51 }
52
53 for (i = 0; i < mod->nr_tests; i++) {
54 struct unit_module_test *test = &mod->tests[i];
55
56 if (test->name == NULL) {
57 core_err(fw, "%s: Unnamed test\n", mod->name);
58 return -1;
59 }
60
61 if (test->fn == NULL) {
62 core_err(fw, "%s: Test %s missing function \n",
63 mod->name, test->name);
64 return -1;
65 }
66 }
67
68 return 0;
69}
70
71static struct unit_module *load_one_module(struct unit_fw *fw,
72 struct dirent *dent)
73{
74 void *lib_handle;
75 struct unit_module *mod;
76
77 core_vbs(fw, 1, "Loading: %s\n", dent->d_name);
78
79 lib_handle = dlopen(dent->d_name, RTLD_NOW);
80 if (lib_handle == NULL) {
81 core_err(fw, "Failed to load %s: %s\n",
82 dent->d_name, dlerror());
83 return NULL;
84 }
85
86 mod = dlsym(lib_handle, "__unit_module__");
87 if (mod == NULL) {
88 core_vbs(fw, 1,
89 "Failed to resolve __unit_module__ in %s: %s\n",
90 dent->d_name, dlerror());
91 return NULL;
92 }
93
94 mod->lib_handle = lib_handle;
95 mod->fw = fw;
96
97 core_vbs(fw, 1, " '%s' contains %lu tests\n", mod->name, mod->nr_tests);
98
99 return mod;
100}
101
102/*
103 * Load all the modules we can from the module load path. Return the list of
104 * loaded module as an array of pointers to modules. The returned list of
105 * modules is NULL terminated.
106 */
107struct unit_module **core_load_modules(struct unit_fw *fw)
108{
109 int nr_modules = 0, i;
110 DIR *load_dir;
111 struct dirent *ent;
112 const char *load_path = args(fw)->unit_load_path;
113 struct unit_module **modules, *mod;
114
115 core_vbs(fw, 1, "Loading modules from %s\n", load_path);
116
117 /*
118 * Open and count the number of files in the dir.
119 */
120 load_dir = opendir(load_path);
121 if (!load_dir) {
122 core_err(fw, "%s: Unable to open dir (%s)\n",
123 load_path, strerror(errno));
124 return NULL;
125 }
126
127 while (readdir(load_dir) != NULL)
128 nr_modules += 1;
129
130 /* '.' and '..' should be skipped. */
131 nr_modules -= 2;
132
133 /*
134 * Now allocate necessary space for storing pointers to the modules and
135 * load the modules. +1 for the last NULL entry.
136 */
137 modules = malloc(sizeof(*modules) * (nr_modules + 1));
138 if (!modules) {
139 core_err(fw, "Out of mem! (huh?)\n");
140 goto err;
141 }
142
143 rewinddir(load_dir);
144 i = 0;
145 while ((ent = readdir(load_dir)) != NULL) {
146 if (strcmp(".", ent->d_name) == 0 ||
147 strcmp("..", ent->d_name) == 0)
148 continue;
149
150 mod = load_one_module(fw, ent);
151 if (mod == NULL)
152 continue;
153
154 if (check_module(fw, mod) != 0)
155 continue;
156
157 modules[i] = mod;
158 i++;
159 }
160
161 modules[i] = NULL;
162 return modules;
163
164err:
165 closedir(load_dir);
166 return NULL;
167}