1/* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the 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, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 */ 21 22#include <apr_hash.h> 23 24#include "svn_hash.h" 25#include "svn_dso.h" 26#include "svn_pools.h" 27#include "svn_private_config.h" 28 29#include "private/svn_mutex.h" 30#include "private/svn_atomic.h" 31#include "private/svn_subr_private.h" 32 33/* A mutex to protect our global pool and cache. */ 34static svn_mutex__t *dso_mutex = NULL; 35 36/* Global pool to allocate DSOs in. */ 37static apr_pool_t *dso_pool; 38 39/* Global cache for storing DSO objects. */ 40static apr_hash_t *dso_cache; 41 42/* Just an arbitrary location in memory... */ 43static int not_there_sentinel; 44 45static volatile svn_atomic_t atomic_init_status = 0; 46 47/* A specific value we store in the dso_cache to indicate that the 48 library wasn't found. This keeps us from allocating extra memory 49 from dso_pool when trying to find libraries we already know aren't 50 there. */ 51#define NOT_THERE ((void *) ¬_there_sentinel) 52 53static svn_error_t * 54atomic_init_func(void *baton, 55 apr_pool_t *pool) 56{ 57 dso_pool = svn_pool_create(NULL); 58 59 SVN_ERR(svn_mutex__init(&dso_mutex, TRUE, dso_pool)); 60 61 dso_cache = apr_hash_make(dso_pool); 62 return SVN_NO_ERROR; 63} 64 65svn_error_t * 66svn_dso_initialize2(void) 67{ 68 SVN_ERR(svn_atomic__init_once(&atomic_init_status, atomic_init_func, 69 NULL, NULL)); 70 71 return SVN_NO_ERROR; 72} 73 74#if APR_HAS_DSO 75static svn_error_t * 76svn_dso_load_internal(apr_dso_handle_t **dso, const char *fname) 77{ 78 *dso = svn_hash_gets(dso_cache, fname); 79 80 /* First check to see if we've been through this before... We do this 81 to avoid calling apr_dso_load multiple times for a given library, 82 which would result in wasting small amounts of memory each time. */ 83 if (*dso == NOT_THERE) 84 { 85 *dso = NULL; 86 return SVN_NO_ERROR; 87 } 88 89 /* If we got nothing back from the cache, try and load the library. */ 90 if (! *dso) 91 { 92 apr_status_t status = apr_dso_load(dso, fname, dso_pool); 93 if (status) 94 { 95#ifdef SVN_DEBUG_DSO 96 char buf[1024]; 97 fprintf(stderr, 98 "Dynamic loading of '%s' failed with the following error:\n%s\n", 99 fname, 100 apr_dso_error(*dso, buf, 1024)); 101#endif 102 *dso = NULL; 103 104 /* It wasn't found, so set the special "we didn't find it" value. */ 105 svn_hash_sets(dso_cache, apr_pstrdup(dso_pool, fname), NOT_THERE); 106 107 return SVN_NO_ERROR; 108 } 109 110 /* Stash the dso so we can use it next time. */ 111 svn_hash_sets(dso_cache, apr_pstrdup(dso_pool, fname), *dso); 112 } 113 114 return SVN_NO_ERROR; 115} 116 117svn_error_t * 118svn_dso_load(apr_dso_handle_t **dso, const char *fname) 119{ 120 SVN_ERR(svn_dso_initialize2()); 121 122 SVN_MUTEX__WITH_LOCK(dso_mutex, svn_dso_load_internal(dso, fname)); 123 124 return SVN_NO_ERROR; 125} 126 127apr_pool_t * 128svn_dso__pool(void) 129{ 130 return dso_pool; 131} 132 133#endif /* APR_HAS_DSO */ 134