1 /*
2 * svn_mutex.c: routines for mutual exclusion.
3 *
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 * ====================================================================
22 */
23
24 #include <apr_portable.h>
25
26 #include "svn_private_config.h"
27 #include "private/svn_atomic.h"
28 #include "private/svn_mutex.h"
29
30 /* With CHECKED set to TRUE, LOCKED and OWNER must be set *after* acquiring
31 * the MUTEX and be reset *before* releasing it again. This is sufficient
32 * because we only want to check whether the current thread already holds
33 * the lock. And the current thread cannot be acquiring / releasing a lock
34 * *while* checking for recursion at the same time.
35 */
36 struct svn_mutex__t
37 {
38 #if APR_HAS_THREADS
39
40 apr_thread_mutex_t *mutex;
41
42 #else
43
44 /* Truly empty structs are not allowed. */
45 int dummy;
46
47 #endif
48 };
49
50 svn_error_t *
svn_mutex__init(svn_mutex__t ** mutex_p,svn_boolean_t mutex_required,apr_pool_t * result_pool)51 svn_mutex__init(svn_mutex__t **mutex_p,
52 svn_boolean_t mutex_required,
53 apr_pool_t *result_pool)
54 {
55 /* always initialize the mutex pointer, even though it is not
56 strictly necessary if APR_HAS_THREADS has not been set */
57 *mutex_p = NULL;
58
59 if (mutex_required)
60 {
61 svn_mutex__t *mutex = apr_pcalloc(result_pool, sizeof(*mutex));
62
63 #if APR_HAS_THREADS
64 apr_status_t status =
65 apr_thread_mutex_create(&mutex->mutex,
66 APR_THREAD_MUTEX_DEFAULT,
67 result_pool);
68 if (status)
69 return svn_error_wrap_apr(status, _("Can't create mutex"));
70 #endif
71
72 *mutex_p = mutex;
73 }
74
75 return SVN_NO_ERROR;
76 }
77
78 svn_error_t *
svn_mutex__lock(svn_mutex__t * mutex)79 svn_mutex__lock(svn_mutex__t *mutex)
80 {
81 if (mutex)
82 {
83 #if APR_HAS_THREADS
84 apr_status_t status = apr_thread_mutex_lock(mutex->mutex);
85 if (status)
86 return svn_error_wrap_apr(status, _("Can't lock mutex"));
87 #endif
88 }
89
90 return SVN_NO_ERROR;
91 }
92
93 svn_error_t *
svn_mutex__unlock(svn_mutex__t * mutex,svn_error_t * err)94 svn_mutex__unlock(svn_mutex__t *mutex,
95 svn_error_t *err)
96 {
97 if (mutex)
98 {
99 #if APR_HAS_THREADS
100 apr_status_t status = apr_thread_mutex_unlock(mutex->mutex);
101 if (status && !err)
102 return svn_error_wrap_apr(status, _("Can't unlock mutex"));
103 #endif
104 }
105
106 return err;
107 }
108
109 #if APR_HAS_THREADS
110
111 apr_thread_mutex_t *
svn_mutex__get(svn_mutex__t * mutex)112 svn_mutex__get(svn_mutex__t *mutex)
113 {
114 return mutex->mutex;
115 }
116
117 #endif
118