1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_general.h"
18#include "apr_lib.h"
19#include "apr_strings.h"
20#include "apr_portable.h"
21#include "apr_arch_proc_mutex.h"
22#include "apr_arch_file_io.h"
23#include <string.h>
24#include <stddef.h>
25
26#define CurrentTid (*_threadid)
27
28static char *fixed_name(const char *fname, apr_pool_t *pool)
29{
30    char *semname;
31
32    if (fname == NULL)
33        semname = NULL;
34    else {
35        /* Semaphores don't live in the file system, fix up the name */
36        while (*fname == '/' || *fname == '\\') {
37            fname++;
38        }
39
40        semname = apr_pstrcat(pool, "/SEM32/", fname, NULL);
41
42        if (semname[8] == ':') {
43            semname[8] = '$';
44        }
45    }
46
47    return semname;
48}
49
50
51
52APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *vmutex)
53{
54    apr_proc_mutex_t *mutex = vmutex;
55    return apr_proc_mutex_destroy(mutex);
56}
57
58APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
59{
60    return NULL;
61}
62
63APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
64{
65    return "os2sem";
66}
67
68APR_DECLARE(const char *) apr_proc_mutex_defname(void)
69{
70    return "os2sem";
71}
72
73
74APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
75                                                const char *fname,
76                                                apr_lockmech_e mech,
77                                                apr_pool_t *pool)
78{
79    apr_proc_mutex_t *new;
80    ULONG rc;
81    char *semname;
82
83    if (mech != APR_LOCK_DEFAULT) {
84        return APR_ENOTIMPL;
85    }
86
87    new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
88    new->pool       = pool;
89    new->owner      = 0;
90    new->lock_count = 0;
91    *mutex = new;
92
93    semname = fixed_name(fname, pool);
94    rc = DosCreateMutexSem(semname, &(new->hMutex), DC_SEM_SHARED, FALSE);
95
96    if (!rc) {
97        apr_pool_cleanup_register(pool, new, apr_proc_mutex_cleanup, apr_pool_cleanup_null);
98    }
99
100    return APR_FROM_OS_ERROR(rc);
101}
102
103
104
105APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
106                                                    const char *fname,
107                                                    apr_pool_t *pool)
108{
109    apr_proc_mutex_t *new;
110    ULONG rc;
111    char *semname;
112
113    new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
114    new->pool       = pool;
115    new->owner      = 0;
116    new->lock_count = 0;
117
118    semname = fixed_name(fname, pool);
119    rc = DosOpenMutexSem(semname, &(new->hMutex));
120    *mutex = new;
121
122    if (!rc) {
123        apr_pool_cleanup_register(pool, new, apr_proc_mutex_cleanup, apr_pool_cleanup_null);
124    }
125
126    return APR_FROM_OS_ERROR(rc);
127}
128
129
130
131APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
132{
133    ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT);
134
135    if (rc == 0) {
136        mutex->owner = CurrentTid;
137        mutex->lock_count++;
138    }
139
140    return APR_FROM_OS_ERROR(rc);
141}
142
143
144
145APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
146{
147    ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN);
148
149    if (rc == 0) {
150        mutex->owner = CurrentTid;
151        mutex->lock_count++;
152    }
153
154    return APR_FROM_OS_ERROR(rc);
155}
156
157
158
159APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
160{
161    ULONG rc;
162
163    if (mutex->owner == CurrentTid && mutex->lock_count > 0) {
164        mutex->lock_count--;
165        rc = DosReleaseMutexSem(mutex->hMutex);
166        return APR_FROM_OS_ERROR(rc);
167    }
168
169    return APR_SUCCESS;
170}
171
172
173
174APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
175{
176    ULONG rc;
177    apr_status_t status = APR_SUCCESS;
178
179    if (mutex->owner == CurrentTid) {
180        while (mutex->lock_count > 0 && status == APR_SUCCESS) {
181            status = apr_proc_mutex_unlock(mutex);
182        }
183    }
184
185    if (status != APR_SUCCESS) {
186        return status;
187    }
188
189    if (mutex->hMutex == 0) {
190        return APR_SUCCESS;
191    }
192
193    rc = DosCloseMutexSem(mutex->hMutex);
194
195    if (!rc) {
196        mutex->hMutex = 0;
197    }
198
199    return APR_FROM_OS_ERROR(rc);
200}
201
202
203
204APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
205
206
207
208/* Implement OS-specific accessors defined in apr_portable.h */
209
210APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
211                                                apr_proc_mutex_t *pmutex)
212{
213    *ospmutex = pmutex->hMutex;
214    return APR_ENOTIMPL;
215}
216
217
218
219APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
220                                                apr_os_proc_mutex_t *ospmutex,
221                                                apr_pool_t *pool)
222{
223    apr_proc_mutex_t *new;
224
225    new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
226    new->pool       = pool;
227    new->owner      = 0;
228    new->lock_count = 0;
229    new->hMutex     = *ospmutex;
230    *pmutex = new;
231
232    return APR_SUCCESS;
233}
234
235