~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/locks/beos/thread_rwlock.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
/*Read/Write locking implementation based on the MultiLock code from
 
18
 * Stephen Beaulieu <hippo@be.com>
 
19
 */
 
20
 
 
21
#include "apr_arch_thread_rwlock.h"
 
22
#include "apr_strings.h"
 
23
#include "apr_portable.h"
 
24
 
 
25
#define BIG_NUM 100000
 
26
 
 
27
static apr_status_t _thread_rw_cleanup(void * data)
 
28
{
 
29
    apr_thread_rwlock_t *mutex = (apr_thread_rwlock_t*)data;
 
30
 
 
31
    if (mutex->ReadCount != 0) {
 
32
        while (atomic_add(&mutex->ReadCount , -1) > 1){
 
33
            release_sem (mutex->Read);
 
34
        }
 
35
    }
 
36
    if (mutex->WriteCount != 0) {
 
37
        while (atomic_add(&mutex->WriteCount , -1) > 1){
 
38
            release_sem (mutex->Write);
 
39
        }
 
40
    }
 
41
    if (mutex->LockCount != 0) {
 
42
        while (atomic_add(&mutex->LockCount , -1) > 1){
 
43
            release_sem (mutex->Lock);
 
44
        }
 
45
    }
 
46
    
 
47
    delete_sem(mutex->Read);
 
48
    delete_sem(mutex->Write);
 
49
    delete_sem(mutex->Lock);
 
50
    return APR_SUCCESS;
 
51
}    
 
52
 
 
53
APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
 
54
                                                   apr_pool_t *pool)
 
55
{
 
56
    apr_thread_rwlock_t *new;
 
57
  
 
58
    new = (apr_thread_rwlock_t *)apr_pcalloc(pool, sizeof(apr_thread_rwlock_t));
 
59
    if (new == NULL){
 
60
        return APR_ENOMEM;
 
61
    }
 
62
    
 
63
    new->pool  = pool;
 
64
    /* we need to make 3 locks... */
 
65
    new->ReadCount = 0;
 
66
    new->WriteCount = 0;
 
67
    new->LockCount = 0;
 
68
    new->Read  = create_sem(0, "APR_ReadLock");
 
69
    new->Write = create_sem(0, "APR_WriteLock");
 
70
    new->Lock  = create_sem(0, "APR_Lock");
 
71
    
 
72
    if (new->Lock < 0 || new->Read < 0 || new->Write < 0) {
 
73
        _thread_rw_cleanup(new);
 
74
        return -1;
 
75
    }
 
76
 
 
77
    apr_pool_cleanup_register(new->pool, (void *)new, _thread_rw_cleanup,
 
78
                              apr_pool_cleanup_null);
 
79
    (*rwlock) = new;
 
80
    return APR_SUCCESS;
 
81
}
 
82
 
 
83
APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
 
84
{
 
85
    int32 rv = APR_SUCCESS;
 
86
 
 
87
    if (find_thread(NULL) == rwlock->writer) {
 
88
        /* we're the writer - no problem */
 
89
        rwlock->Nested++;
 
90
    } else {
 
91
        /* we're not the writer */
 
92
        int32 r = atomic_add(&rwlock->ReadCount, 1);
 
93
        if (r < 0) {
 
94
            /* Oh dear, writer holds lock, wait for sem */
 
95
            rv = acquire_sem_etc(rwlock->Read, 1, B_DO_NOT_RESCHEDULE,
 
96
                                 B_INFINITE_TIMEOUT);
 
97
        }
 
98
    }
 
99
 
 
100
    return rv;
 
101
}
 
102
 
 
103
APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
 
104
{
 
105
    return APR_ENOTIMPL;
 
106
}
 
107
 
 
108
APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
 
109
{
 
110
    int rv = APR_SUCCESS;
 
111
 
 
112
    if (find_thread(NULL) == rwlock->writer) {
 
113
        rwlock->Nested++;
 
114
    } else {
 
115
        /* we're not the writer... */
 
116
        if (atomic_add(&rwlock->LockCount, 1) >= 1) {
 
117
            /* we're locked - acquire the sem */
 
118
            rv = acquire_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE,
 
119
                                 B_INFINITE_TIMEOUT);
 
120
        }
 
121
        if (rv == APR_SUCCESS) {
 
122
            /* decrement the ReadCount to a large -ve number so that
 
123
             * we block on new readers...
 
124
             */
 
125
            int32 readers = atomic_add(&rwlock->ReadCount, -BIG_NUM);
 
126
            if (readers > 0) {
 
127
                /* readers are holding the lock */
 
128
                rv = acquire_sem_etc(rwlock->Write, readers, B_DO_NOT_RESCHEDULE,
 
129
                                     B_INFINITE_TIMEOUT);
 
130
            }
 
131
            if (rv == APR_SUCCESS)
 
132
                rwlock->writer = find_thread(NULL);
 
133
        }
 
134
    }
 
135
    
 
136
    return rv;
 
137
}
 
138
 
 
139
APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
 
140
{
 
141
    return APR_ENOTIMPL;
 
142
}
 
143
 
 
144
APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
 
145
{
 
146
    apr_status_t rv = APR_SUCCESS;
 
147
    int32 readers;
 
148
 
 
149
    /* we know we hold the lock, so don't check it :) */
 
150
    if (find_thread(NULL) == rwlock->writer) {
 
151
    /* we know we hold the lock, so don't check it :) */
 
152
        if (rwlock->Nested > 1) {
 
153
            /* we're recursively locked */
 
154
            rwlock->Nested--;
 
155
            return APR_SUCCESS;
 
156
        }
 
157
        /* OK so we need to release the sem if we have it :) */
 
158
        readers = atomic_add(&rwlock->ReadCount, BIG_NUM) + BIG_NUM;
 
159
        if (readers > 0) {
 
160
            rv = release_sem_etc(rwlock->Read, readers, B_DO_NOT_RESCHEDULE);
 
161
        }
 
162
        if (rv == APR_SUCCESS) {
 
163
            rwlock->writer = -1;
 
164
            if (atomic_add(&rwlock->LockCount, -1) > 1) {
 
165
                rv = release_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE);
 
166
            }
 
167
        }
 
168
    } else {
 
169
       /* We weren't the Writer, so just release the ReadCount... */
 
170
       if (atomic_add(&rwlock->ReadCount, -1) < 0) {
 
171
            /* we have a writer waiting for the lock, so release it */
 
172
            rv = release_sem_etc(rwlock->Write, 1, B_DO_NOT_RESCHEDULE);
 
173
        }
 
174
    }
 
175
 
 
176
    return rv;
 
177
}
 
178
 
 
179
APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
 
180
{
 
181
    apr_status_t stat;
 
182
    if ((stat = _thread_rw_cleanup(rwlock)) == APR_SUCCESS) {
 
183
        apr_pool_cleanup_kill(rwlock->pool, rwlock, _thread_rw_cleanup);
 
184
        return APR_SUCCESS;
 
185
    }
 
186
    return stat;
 
187
}
 
188
 
 
189
APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
 
190