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