123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /****************************************************************************
- * libs/libc/modlib/modlib_registry.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #include <string.h>
- #include <debug.h>
- #include <errno.h>
- #include <nuttx/semaphore.h>
- #include <nuttx/lib/modlib.h>
- /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
- #define NO_HOLDER ((pid_t)-1)
- /****************************************************************************
- * Private Types
- ****************************************************************************/
- struct mod_registrylock_s
- {
- sem_t lock; /* The actual registry lock */
- pid_t holder; /* The PID of the current holder of the lock */
- int16_t count; /* The number of nested calls to modlib_registry_lock */
- };
- /****************************************************************************
- * Private Data
- ****************************************************************************/
- static struct mod_registrylock_s g_modlock =
- {
- SEM_INITIALIZER(1), /* lock */
- NO_HOLDER, /* pid */
- 0 /* count */
- };
- static FAR struct module_s *g_mod_registry;
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: modlib_registry_lock
- *
- * Description:
- * Get exclusive access to the module registry.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * None
- *
- ****************************************************************************/
- void modlib_registry_lock(void)
- {
- pid_t me;
- int ret;
- /* Do we already hold the semaphore? */
- me = getpid();
- if (me == g_modlock.holder)
- {
- /* Yes... just increment the count */
- g_modlock.count++;
- DEBUGASSERT(g_modlock.count > 0);
- }
- /* Take the semaphore (perhaps waiting) */
- else
- {
- while ((ret = _SEM_WAIT(&g_modlock.lock)) < 0)
- {
- /* The only case that an error should occur here is if
- * the wait was awakened by a signal.
- */
- DEBUGASSERT(_SEM_ERRNO(ret) == EINTR ||
- _SEM_ERRNO(ret) == ECANCELED);
- UNUSED(ret);
- }
- /* No we hold the semaphore */
- g_modlock.holder = me;
- g_modlock.count = 1;
- }
- }
- /****************************************************************************
- * Name: modlib_registry_unlock
- *
- * Description:
- * Relinquish the lock on the module registry
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * None
- *
- ****************************************************************************/
- void modlib_registry_unlock(void)
- {
- DEBUGASSERT(g_modlock.holder == getpid());
- /* Is this our last count on the semaphore? */
- if (g_modlock.count > 1)
- {
- /* No.. just decrement the count */
- g_modlock.count--;
- }
- /* Yes.. then we can really release the semaphore */
- else
- {
- g_modlock.holder = NO_HOLDER;
- g_modlock.count = 0;
- _SEM_POST(&g_modlock.lock);
- }
- }
- /****************************************************************************
- * Name: modlib_registry_add
- *
- * Description:
- * Add a new entry to the module registry.
- *
- * Input Parameters:
- * modp - The module data structure to be registered.
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * The caller holds the lock on the module registry.
- *
- ****************************************************************************/
- void modlib_registry_add(FAR struct module_s *modp)
- {
- DEBUGASSERT(modp);
- modp->flink = g_mod_registry;
- g_mod_registry = modp;
- }
- /****************************************************************************
- * Name: modlib_registry_del
- *
- * Description:
- * Remove a module entry from the registry
- *
- * Input Parameters:
- * modp - The registry entry to be removed.
- *
- * Returned Value:
- * Zero (OK) is returned if the registry entry was deleted. Otherwise,
- * a negated errno value is returned.
- *
- * Assumptions:
- * The caller holds the lock on the module registry.
- *
- ****************************************************************************/
- int modlib_registry_del(FAR struct module_s *modp)
- {
- FAR struct module_s *prev;
- FAR struct module_s *curr;
- for (prev = NULL, curr = g_mod_registry;
- curr != NULL && curr != modp;
- prev = curr, curr = curr->flink);
- if (curr == NULL)
- {
- berr("ERROR: Could not find module entry\n");
- return -ENOENT;
- }
- if (prev == NULL)
- {
- g_mod_registry = modp->flink;
- }
- else
- {
- prev->flink = modp->flink;
- }
- modp->flink = NULL;
- return OK;
- }
- /****************************************************************************
- * Name: modlib_registry_find
- *
- * Description:
- * Find an entry in the module registry using the name of the module.
- *
- * Input Parameters:
- * modname - The name of the module to be found
- *
- * Returned Value:
- * If the registry entry is found, a pointer to the module entry is
- * returned. NULL is returned if the entry is not found.
- *
- * Assumptions:
- * The caller holds the lock on the module registry.
- *
- ****************************************************************************/
- #ifdef HAVE_MODLIB_NAMES
- FAR struct module_s *modlib_registry_find(FAR const char *modname)
- {
- FAR struct module_s *modp;
- for (modp = g_mod_registry;
- modp != NULL && strncmp(modp->modname, modname, MODLIB_NAMEMAX) != 0;
- modp = modp->flink);
- return modp;
- }
- #endif
- /****************************************************************************
- * Name: modlib_registry_verify
- *
- * Description:
- * Verify that a module handle is valid by traversing the module list and
- * assuring that the module still resides in the list. If it does not,
- * the handle is probably a stale pointer.
- *
- * Input Parameters:
- * modp - The registry entry to be verified.
- *
- * Returned Value:
- * Returns OK is the module is valid; -ENOENT otherwise.
- *
- * Assumptions:
- * The caller holds the lock on the module registry.
- *
- ****************************************************************************/
- int modlib_registry_verify(FAR struct module_s *modp)
- {
- FAR struct module_s *node;
- for (node = g_mod_registry; node != NULL; node = node->flink)
- {
- if (node == modp)
- {
- return OK;
- }
- }
- return -ENOENT;
- }
- /****************************************************************************
- * Name: modlib_registry_foreach
- *
- * Description:
- * Visit each module in the registry
- *
- * Input Parameters:
- * callback - This callback function was be called for each entry in the
- * registry.
- * arg - This opaque argument will be passed to the callback function.
- *
- * Returned Value:
- * This function normally returns zero (OK). If, however, any callback
- * function returns a non-zero value, the traversal will be terminated and
- * that non-zero value will be returned.
- *
- ****************************************************************************/
- int modlib_registry_foreach(mod_callback_t callback, FAR void *arg)
- {
- FAR struct module_s *modp;
- int ret = OK;
- /* Get exclusive access to the module registry */
- modlib_registry_lock();
- /* Visit each installed module */
- for (modp = g_mod_registry; modp != NULL; modp = modp->flink)
- {
- /* Perform the callback */
- ret = callback(modp, arg);
- if (ret != 0)
- {
- break;
- }
- }
- modlib_registry_unlock();
- return ret;
- }
|