upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / shmem / win32 / shm.c
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_errno.h"
19 #include "apr_file_io.h"
20 #include "apr_shm.h"
21 #include "apr_arch_file_io.h"
22
23 typedef struct memblock_t {
24     apr_size_t size;
25     apr_size_t length;
26 } memblock_t;
27
28 struct apr_shm_t {
29     apr_pool_t *pool;
30     memblock_t *memblk;
31     void       *usrmem;
32     apr_size_t  size;
33     apr_size_t  length;
34     HANDLE      hMap;
35 };
36
37 static apr_status_t shm_cleanup(void* shm)
38 {
39     apr_status_t rv = APR_SUCCESS;
40     apr_shm_t *m = shm;
41     
42     if (UnmapViewOfFile(m->memblk)) {
43         rv = apr_get_os_error();
44     }
45     if (CloseHandle(m->hMap)) {
46         return (rv != APR_SUCCESS) ? rv : apr_get_os_error();
47     }
48     /* ### Do we want to make a point of unlinking m->file here? 
49      * Need to add the fname to the apr_shm_t, in that case.
50      */
51     return rv;
52 }
53
54 APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
55                                          apr_size_t reqsize,
56                                          const char *file,
57                                          apr_pool_t *pool)
58 {
59     static apr_size_t memblock = 0;
60     HANDLE hMap, hFile;
61     apr_status_t rv;
62     apr_size_t size;
63     apr_file_t *f;
64     void *base;
65     void *mapkey;
66     DWORD err;
67
68     reqsize += sizeof(memblock_t);
69
70     if (!memblock)
71     {
72         SYSTEM_INFO si;
73         GetSystemInfo(&si);
74         memblock = si.dwAllocationGranularity;
75     }   
76
77     /* Compute the granualar multiple of the pagesize */
78     size = memblock * (1 + (reqsize - 1) / memblock);
79
80     if (!file) {
81         /* Do Anonymous, which must be passed as a duplicated handle */
82 #ifndef _WIN32_WCE
83         hFile = INVALID_HANDLE_VALUE;
84 #endif
85         mapkey = NULL;
86     }
87     else {
88         /* Do file backed, which is not an inherited handle 
89          * While we could open APR_EXCL, it doesn't seem that Unix
90          * ever did.  Ignore that error here, but fail later when
91          * we discover we aren't the creator of the file map object.
92          */
93         rv = apr_file_open(&f, file,
94                            APR_READ | APR_WRITE | APR_BINARY | APR_CREATE,
95                            APR_UREAD | APR_UWRITE, pool);
96         if ((rv != APR_SUCCESS)
97                 || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) {
98             return rv;
99         }
100         rv = apr_file_trunc(f, size);
101
102         /* res_name_from_filename turns file into a pseudo-name
103          * without slashes or backslashes, and prepends the \global
104          * prefix on Win2K and later
105          */
106         mapkey = res_name_from_filename(file, 1, pool);
107     }
108
109 #if APR_HAS_UNICODE_FS
110     IF_WIN_OS_IS_UNICODE
111     {
112         hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 0, size, mapkey);
113     }
114 #endif
115 #if APR_HAS_ANSI_FS
116     ELSE_WIN_OS_IS_ANSI
117     {
118         hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, size, mapkey);
119     }
120 #endif
121     err = apr_get_os_error();
122
123     if (file) {
124         apr_file_close(f);
125     }
126
127     if (hMap && APR_STATUS_IS_EEXIST(err)) {
128         CloseHandle(hMap);
129         return APR_EEXIST;
130     }
131     if (!hMap) {
132         return err;
133     }
134     
135     base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE,
136                          0, 0, size);
137     if (!base) {
138         CloseHandle(hMap);
139         return apr_get_os_error();
140     }
141     
142     *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
143     (*m)->pool = pool;
144     (*m)->hMap = hMap;
145     (*m)->memblk = base;
146     (*m)->size = size;
147
148     (*m)->usrmem = (char*)base + sizeof(memblock_t);
149     (*m)->length = reqsize - sizeof(memblock_t);;
150     
151     (*m)->memblk->length = (*m)->length;
152     (*m)->memblk->size = (*m)->size;
153
154     apr_pool_cleanup_register((*m)->pool, *m, 
155                               shm_cleanup, apr_pool_cleanup_null);
156     return APR_SUCCESS;
157 }
158
159 APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) 
160 {
161     apr_status_t rv = shm_cleanup(m);
162     apr_pool_cleanup_kill(m->pool, m, shm_cleanup);
163     return rv;
164 }
165
166 APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
167                                          const char *file,
168                                          apr_pool_t *pool)
169 {
170     HANDLE hMap;
171     void *mapkey;
172     void *base;
173
174     if (!file) {
175         return APR_EINVAL;
176     }
177     else {
178         /* res_name_from_filename turns file into a pseudo-name
179          * without slashes or backslashes, and prepends the \global
180          * prefix on Win2K and later
181          */
182         mapkey = res_name_from_filename(file, 1, pool);
183     }
184
185 #if APR_HAS_UNICODE_FS
186     IF_WIN_OS_IS_UNICODE
187     {
188 #ifndef _WIN32_WCE
189         hMap = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey);
190 #else
191         /* The WCE 3.0 lacks OpenFileMapping. So we emulate one with
192          * opening the existing shmem and reading its size from the header 
193          */
194         hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 
195                                   PAGE_READWRITE, 0, sizeof(apr_shm_t), mapkey);
196 #endif
197     }
198 #endif
199 #if APR_HAS_ANSI_FS
200     ELSE_WIN_OS_IS_ANSI
201     {
202         hMap = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey);
203     }
204 #endif
205
206     if (!hMap) {
207         return apr_get_os_error();
208     }
209     
210     base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
211     if (!base) {
212         CloseHandle(hMap);
213         return apr_get_os_error();
214     }
215     
216     *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
217     (*m)->pool = pool;
218     (*m)->memblk = base;
219     /* Real (*m)->mem->size could be recovered with VirtualQuery */
220     (*m)->size = (*m)->memblk->size;
221 #if _WIN32_WCE
222     /* Reopen with real size  */
223     UnmapViewOfFile(base);
224     CloseHandle(hMap);
225
226     hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 
227                               PAGE_READWRITE, 0, (*m)->size, mapkey);
228     if (!hMap) {
229         return apr_get_os_error();
230     }
231     base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
232     if (!base) {
233         CloseHandle(hMap);
234         return apr_get_os_error();
235     }    
236 #endif
237     (*m)->hMap = hMap;
238     (*m)->length = (*m)->memblk->length;
239     (*m)->usrmem = (char*)base + sizeof(memblock_t);
240     apr_pool_cleanup_register((*m)->pool, *m, 
241                               shm_cleanup, apr_pool_cleanup_null);
242     return APR_SUCCESS;
243 }
244
245 APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
246 {
247     apr_status_t rv = shm_cleanup(m);
248     apr_pool_cleanup_kill(m->pool, m, shm_cleanup);
249     return rv;
250 }
251
252 APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
253 {
254     return m->usrmem;
255 }
256
257 APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
258 {
259     return m->length;
260 }
261
262 APR_POOL_IMPLEMENT_ACCESSOR(shm)
263
264 APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
265                                          apr_shm_t *shm)
266 {
267     *osshm = shm->hMap;
268     return APR_SUCCESS;
269 }
270
271 APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
272                                          apr_os_shm_t *osshm,
273                                          apr_pool_t *pool)
274 {
275     void* base;
276     base = MapViewOfFile(*osshm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
277     if (!base) {
278         return apr_get_os_error();
279     }
280     
281     *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
282     (*m)->pool = pool;
283     (*m)->hMap = *osshm;
284     (*m)->memblk = base;
285     (*m)->usrmem = (char*)base + sizeof(memblock_t);
286     /* Real (*m)->mem->size could be recovered with VirtualQuery */
287     (*m)->size = (*m)->memblk->size;
288     (*m)->length = (*m)->memblk->length;
289
290     apr_pool_cleanup_register((*m)->pool, *m, 
291                               shm_cleanup, apr_pool_cleanup_null);
292     return APR_SUCCESS;
293 }    
294