Back to index

glibc  2.9
Defines | Functions | Variables
gconv_dl.c File Reference
#include <assert.h>
#include <dlfcn.h>
#include <inttypes.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <bits/libc-lock.h>
#include <sys/param.h>
#include <gconv_int.h>
#include <sysdep.h>

Go to the source code of this file.

Defines

#define TRIES_BEFORE_UNLOAD   2

Functions

static int known_compare (const void *p1, const void *p2)
struct __gconv_loaded_object
*internal_function 
__gconv_find_shlib (const char *name)
static void do_release_shlib (void *nodep, VISIT value, int level)
void internal_function __gconv_release_shlib (struct __gconv_loaded_object *handle)
static void
__libc_freeres_fn_section 
do_release_all (void *nodep)
 libc_freeres_fn (free_mem)

Variables

static void * loaded
static struct
__gconv_loaded_object
release_handle

Define Documentation

#define TRIES_BEFORE_UNLOAD   2

Definition at line 48 of file gconv_dl.c.


Function Documentation

Definition at line 70 of file gconv_dl.c.

{
  struct __gconv_loaded_object *found;
  void *keyp;

  /* Search the tree of shared objects previously requested.  Data in
     the tree are `loaded_object' structures, whose first member is a
     `const char *', the lookup key.  The search returns a pointer to
     the tree node structure; the first member of the is a pointer to
     our structure (i.e. what will be a `loaded_object'); since the
     first member of that is the lookup key string, &FCT_NAME is close
     enough to a pointer to our structure to use as a lookup key that
     will be passed to `known_compare' (above).  */

  keyp = __tfind (&name, &loaded, known_compare);
  if (keyp == NULL)
    {
      /* This name was not known before.  */
      size_t namelen = strlen (name) + 1;

      found = malloc (sizeof (struct __gconv_loaded_object) + namelen);
      if (found != NULL)
       {
         /* Point the tree node at this new structure.  */
         found->name = (char *) memcpy (found + 1, name, namelen);
         found->counter = -TRIES_BEFORE_UNLOAD - 1;
         found->handle = NULL;

         if (__builtin_expect (__tsearch (found, &loaded, known_compare)
                            == NULL, 0))
           {
             /* Something went wrong while inserting the entry.  */
             free (found);
             found = NULL;
           }
       }
    }
  else
    found = *(struct __gconv_loaded_object **) keyp;

  /* Try to load the shared object if the usage count is 0.  This
     implies that if the shared object is not loadable, the handle is
     NULL and the usage count > 0.  */
  if (found != NULL)
    {
      if (found->counter < -TRIES_BEFORE_UNLOAD)
       {
         assert (found->handle == NULL);
         found->handle = __libc_dlopen (found->name);
         if (found->handle != NULL)
           {
             found->fct = __libc_dlsym (found->handle, "gconv");
             if (found->fct == NULL)
              {
                /* Argh, no conversion function.  There is something
                     wrong here.  */
                __gconv_release_shlib (found);
                found = NULL;
              }
             else
              {
                found->init_fct = __libc_dlsym (found->handle, "gconv_init");
                found->end_fct = __libc_dlsym (found->handle, "gconv_end");

#ifdef PTR_MANGLE
                PTR_MANGLE (found->fct);
                if (found->init_fct != NULL)
                  PTR_MANGLE (found->init_fct);
                if (found->end_fct !=  NULL)
                  PTR_MANGLE (found->end_fct);
#endif

                /* We have succeeded in loading the shared object.  */
                found->counter = 1;
              }
           }
         else
           /* Error while loading the shared object.  */
           found = NULL;
       }
      else if (found->handle != NULL)
       found->counter = MAX (found->counter + 1, 1);
    }

  return found;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 191 of file gconv_dl.c.

{
  /* Urgh, this is ugly but we have no other possibility.  */
  release_handle = handle;

  /* Process all entries.  Please note that we also visit entries
     with release counts <= 0.  This way we can finally unload them
     if necessary.  */
  __twalk (loaded, (__action_fn_t) do_release_shlib);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void __libc_freeres_fn_section do_release_all ( void *  nodep) [static]

Definition at line 205 of file gconv_dl.c.

{
  struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;

  /* Unload the shared object.  */
  if (obj->handle != NULL)
    __libc_dlclose (obj->handle);

  free (obj);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_release_shlib ( void *  nodep,
VISIT  value,
int  level 
) [static]

Definition at line 164 of file gconv_dl.c.

{
  struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;

  if (value != preorder && value != leaf)
    return;

  if (obj == release_handle)
    {
      /* This is the object we want to unload.  Now decrement the
        reference counter.  */
      assert (obj->counter > 0);
      --obj->counter;
    }
  else if (obj->counter <= 0 && obj->counter >= -TRIES_BEFORE_UNLOAD
          && --obj->counter < -TRIES_BEFORE_UNLOAD && obj->handle != NULL)
    {
      /* Unload the shared object.  */
      __libc_dlclose (obj->handle);
      obj->handle = NULL;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int known_compare ( const void *  p1,
const void *  p2 
) [static]

Definition at line 56 of file gconv_dl.c.

{
  const struct __gconv_loaded_object *s1 =
    (const struct __gconv_loaded_object *) p1;
  const struct __gconv_loaded_object *s2 =
    (const struct __gconv_loaded_object *) p2;

  return strcmp (s1->name, s2->name);
}

Here is the caller graph for this function:

libc_freeres_fn ( free_mem  )

Definition at line 216 of file gconv_dl.c.

Here is the call graph for this function:


Variable Documentation

void* loaded [static]

Definition at line 52 of file gconv_dl.c.

Definition at line 161 of file gconv_dl.c.