mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
elf: Add fast path to dlopen for fully-opened maps
If the map is already fully open (has matching flags and its own scope allocated), it is not necessary to unprotected memory during dlopen.
This commit is contained in:
parent
edc6842bbc
commit
b05e78d473
1 changed files with 31 additions and 5 deletions
|
@ -492,6 +492,23 @@ call_dl_init (void *closure)
|
|||
_dl_init (args->map, args->argc, args->argv, args->env);
|
||||
}
|
||||
|
||||
/* Return true if the object does not need any processing beyond the
|
||||
l_direct_opencount update. Needs to be kept in sync with the logic
|
||||
in dl_open_worker_begin after the l->l_searchlist.r_list != NULL check.
|
||||
MODE is the dlopen mode argument. */
|
||||
static bool
|
||||
is_already_fully_open (struct link_map *map, int mode)
|
||||
{
|
||||
return (map != NULL /* An existing map was found. */
|
||||
/* dlopen completed initialization of this map. Maps with
|
||||
l_type == lt_library start out as partially initialized. */
|
||||
&& map->l_searchlist.r_list != NULL
|
||||
/* The object is already in the global scope if requested. */
|
||||
&& (!(mode & RTLD_GLOBAL) || map->l_global)
|
||||
/* The object is already NODELETE if requested. */
|
||||
&& (!(mode & RTLD_NODELETE) || map->l_nodelete_active));
|
||||
}
|
||||
|
||||
static void
|
||||
dl_open_worker_begin (void *a)
|
||||
{
|
||||
|
@ -513,9 +530,10 @@ dl_open_worker_begin (void *a)
|
|||
_dl_debug_initialize (0, args->nsid);
|
||||
|
||||
/* Load the named object. */
|
||||
struct link_map *new;
|
||||
args->map = new = _dl_map_object (args->caller_map, file, lt_loaded, 0,
|
||||
mode | __RTLD_CALLMAP, args->nsid);
|
||||
struct link_map *new = args->map;
|
||||
if (new == NULL)
|
||||
args->map = new = _dl_map_new_object (args->caller_map, file, lt_loaded, 0,
|
||||
mode | __RTLD_CALLMAP, args->nsid);
|
||||
|
||||
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
|
||||
set and the object is not already loaded. */
|
||||
|
@ -532,7 +550,7 @@ dl_open_worker_begin (void *a)
|
|||
/* This object is directly loaded. */
|
||||
++new->l_direct_opencount;
|
||||
|
||||
/* It was already open. */
|
||||
/* It was already open. See is_already_fully_open above. */
|
||||
if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
|
||||
{
|
||||
/* Let the user know about the opencount. */
|
||||
|
@ -834,7 +852,6 @@ no more namespaces available for dlmopen()"));
|
|||
struct dl_open_args args;
|
||||
args.file = file;
|
||||
args.mode = mode;
|
||||
args.map = NULL;
|
||||
args.nsid = nsid;
|
||||
/* args.libc_already_loaded is always assigned by dl_open_worker
|
||||
(before any explicit/non-local returns). */
|
||||
|
@ -859,6 +876,15 @@ no more namespaces available for dlmopen()"));
|
|||
else
|
||||
args.caller_map = NULL;
|
||||
|
||||
args.map = _dl_lookup_map (args.nsid, file);
|
||||
if (is_already_fully_open (args.map, mode))
|
||||
{
|
||||
/* We can use the fast path. */
|
||||
++args.map->l_direct_opencount;
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
return args.map;
|
||||
}
|
||||
|
||||
struct dl_exception exception;
|
||||
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue