modlib_registry.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /****************************************************************************
  2. * libs/libc/modlib/modlib_registry.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <string.h>
  25. #include <debug.h>
  26. #include <errno.h>
  27. #include <nuttx/semaphore.h>
  28. #include <nuttx/lib/modlib.h>
  29. /****************************************************************************
  30. * Pre-processor Definitions
  31. ****************************************************************************/
  32. #define NO_HOLDER ((pid_t)-1)
  33. /****************************************************************************
  34. * Private Types
  35. ****************************************************************************/
  36. struct mod_registrylock_s
  37. {
  38. sem_t lock; /* The actual registry lock */
  39. pid_t holder; /* The PID of the current holder of the lock */
  40. int16_t count; /* The number of nested calls to modlib_registry_lock */
  41. };
  42. /****************************************************************************
  43. * Private Data
  44. ****************************************************************************/
  45. static struct mod_registrylock_s g_modlock =
  46. {
  47. SEM_INITIALIZER(1), /* lock */
  48. NO_HOLDER, /* pid */
  49. 0 /* count */
  50. };
  51. static FAR struct module_s *g_mod_registry;
  52. /****************************************************************************
  53. * Public Functions
  54. ****************************************************************************/
  55. /****************************************************************************
  56. * Name: modlib_registry_lock
  57. *
  58. * Description:
  59. * Get exclusive access to the module registry.
  60. *
  61. * Input Parameters:
  62. * None
  63. *
  64. * Returned Value:
  65. * None
  66. *
  67. ****************************************************************************/
  68. void modlib_registry_lock(void)
  69. {
  70. pid_t me;
  71. int ret;
  72. /* Do we already hold the semaphore? */
  73. me = getpid();
  74. if (me == g_modlock.holder)
  75. {
  76. /* Yes... just increment the count */
  77. g_modlock.count++;
  78. DEBUGASSERT(g_modlock.count > 0);
  79. }
  80. /* Take the semaphore (perhaps waiting) */
  81. else
  82. {
  83. while ((ret = _SEM_WAIT(&g_modlock.lock)) < 0)
  84. {
  85. /* The only case that an error should occur here is if
  86. * the wait was awakened by a signal.
  87. */
  88. DEBUGASSERT(_SEM_ERRNO(ret) == EINTR ||
  89. _SEM_ERRNO(ret) == ECANCELED);
  90. UNUSED(ret);
  91. }
  92. /* No we hold the semaphore */
  93. g_modlock.holder = me;
  94. g_modlock.count = 1;
  95. }
  96. }
  97. /****************************************************************************
  98. * Name: modlib_registry_unlock
  99. *
  100. * Description:
  101. * Relinquish the lock on the module registry
  102. *
  103. * Input Parameters:
  104. * None
  105. *
  106. * Returned Value:
  107. * None
  108. *
  109. ****************************************************************************/
  110. void modlib_registry_unlock(void)
  111. {
  112. DEBUGASSERT(g_modlock.holder == getpid());
  113. /* Is this our last count on the semaphore? */
  114. if (g_modlock.count > 1)
  115. {
  116. /* No.. just decrement the count */
  117. g_modlock.count--;
  118. }
  119. /* Yes.. then we can really release the semaphore */
  120. else
  121. {
  122. g_modlock.holder = NO_HOLDER;
  123. g_modlock.count = 0;
  124. _SEM_POST(&g_modlock.lock);
  125. }
  126. }
  127. /****************************************************************************
  128. * Name: modlib_registry_add
  129. *
  130. * Description:
  131. * Add a new entry to the module registry.
  132. *
  133. * Input Parameters:
  134. * modp - The module data structure to be registered.
  135. *
  136. * Returned Value:
  137. * None
  138. *
  139. * Assumptions:
  140. * The caller holds the lock on the module registry.
  141. *
  142. ****************************************************************************/
  143. void modlib_registry_add(FAR struct module_s *modp)
  144. {
  145. DEBUGASSERT(modp);
  146. modp->flink = g_mod_registry;
  147. g_mod_registry = modp;
  148. }
  149. /****************************************************************************
  150. * Name: modlib_registry_del
  151. *
  152. * Description:
  153. * Remove a module entry from the registry
  154. *
  155. * Input Parameters:
  156. * modp - The registry entry to be removed.
  157. *
  158. * Returned Value:
  159. * Zero (OK) is returned if the registry entry was deleted. Otherwise,
  160. * a negated errno value is returned.
  161. *
  162. * Assumptions:
  163. * The caller holds the lock on the module registry.
  164. *
  165. ****************************************************************************/
  166. int modlib_registry_del(FAR struct module_s *modp)
  167. {
  168. FAR struct module_s *prev;
  169. FAR struct module_s *curr;
  170. for (prev = NULL, curr = g_mod_registry;
  171. curr != NULL && curr != modp;
  172. prev = curr, curr = curr->flink);
  173. if (curr == NULL)
  174. {
  175. berr("ERROR: Could not find module entry\n");
  176. return -ENOENT;
  177. }
  178. if (prev == NULL)
  179. {
  180. g_mod_registry = modp->flink;
  181. }
  182. else
  183. {
  184. prev->flink = modp->flink;
  185. }
  186. modp->flink = NULL;
  187. return OK;
  188. }
  189. /****************************************************************************
  190. * Name: modlib_registry_find
  191. *
  192. * Description:
  193. * Find an entry in the module registry using the name of the module.
  194. *
  195. * Input Parameters:
  196. * modname - The name of the module to be found
  197. *
  198. * Returned Value:
  199. * If the registry entry is found, a pointer to the module entry is
  200. * returned. NULL is returned if the entry is not found.
  201. *
  202. * Assumptions:
  203. * The caller holds the lock on the module registry.
  204. *
  205. ****************************************************************************/
  206. #ifdef HAVE_MODLIB_NAMES
  207. FAR struct module_s *modlib_registry_find(FAR const char *modname)
  208. {
  209. FAR struct module_s *modp;
  210. for (modp = g_mod_registry;
  211. modp != NULL && strncmp(modp->modname, modname, MODLIB_NAMEMAX) != 0;
  212. modp = modp->flink);
  213. return modp;
  214. }
  215. #endif
  216. /****************************************************************************
  217. * Name: modlib_registry_verify
  218. *
  219. * Description:
  220. * Verify that a module handle is valid by traversing the module list and
  221. * assuring that the module still resides in the list. If it does not,
  222. * the handle is probably a stale pointer.
  223. *
  224. * Input Parameters:
  225. * modp - The registry entry to be verified.
  226. *
  227. * Returned Value:
  228. * Returns OK is the module is valid; -ENOENT otherwise.
  229. *
  230. * Assumptions:
  231. * The caller holds the lock on the module registry.
  232. *
  233. ****************************************************************************/
  234. int modlib_registry_verify(FAR struct module_s *modp)
  235. {
  236. FAR struct module_s *node;
  237. for (node = g_mod_registry; node != NULL; node = node->flink)
  238. {
  239. if (node == modp)
  240. {
  241. return OK;
  242. }
  243. }
  244. return -ENOENT;
  245. }
  246. /****************************************************************************
  247. * Name: modlib_registry_foreach
  248. *
  249. * Description:
  250. * Visit each module in the registry
  251. *
  252. * Input Parameters:
  253. * callback - This callback function was be called for each entry in the
  254. * registry.
  255. * arg - This opaque argument will be passed to the callback function.
  256. *
  257. * Returned Value:
  258. * This function normally returns zero (OK). If, however, any callback
  259. * function returns a non-zero value, the traversal will be terminated and
  260. * that non-zero value will be returned.
  261. *
  262. ****************************************************************************/
  263. int modlib_registry_foreach(mod_callback_t callback, FAR void *arg)
  264. {
  265. FAR struct module_s *modp;
  266. int ret = OK;
  267. /* Get exclusive access to the module registry */
  268. modlib_registry_lock();
  269. /* Visit each installed module */
  270. for (modp = g_mod_registry; modp != NULL; modp = modp->flink)
  271. {
  272. /* Perform the callback */
  273. ret = callback(modp, arg);
  274. if (ret != 0)
  275. {
  276. break;
  277. }
  278. }
  279. modlib_registry_unlock();
  280. return ret;
  281. }