bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / mmap / win32 / mmap.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.h"
18 #include "apr_private.h"
19 #include "apr_general.h"
20 #include "apr_mmap.h"
21 #include "apr_errno.h"
22 #include "apr_arch_file_io.h"
23 #include "apr_portable.h"
24 #include "apr_strings.h"
25
26 #if APR_HAS_MMAP
27
28 static apr_status_t mmap_cleanup(void *themmap)
29 {
30     apr_mmap_t *mm = themmap;
31     apr_mmap_t *next = APR_RING_NEXT(mm,link);
32     apr_status_t rv = 0;
33
34     /* we no longer refer to the mmaped region */
35     APR_RING_REMOVE(mm,link);
36     APR_RING_NEXT(mm,link) = NULL;
37     APR_RING_PREV(mm,link) = NULL;
38
39     if (next != mm) {
40         /* more references exist, so we're done */
41         return APR_SUCCESS;
42     }
43
44     if (mm->mv) {
45         if (!UnmapViewOfFile(mm->mv))
46         {
47             apr_status_t rv = apr_get_os_error();
48             CloseHandle(mm->mhandle);
49             mm->mv = NULL;
50             mm->mhandle = NULL;
51             return rv;
52         }
53         mm->mv = NULL;
54     }
55     if (mm->mhandle) 
56     {
57         if (!CloseHandle(mm->mhandle))
58         {
59             apr_status_t rv = apr_get_os_error();
60             CloseHandle(mm->mhandle);
61             mm->mhandle = NULL;
62             return rv;
63         }
64         mm->mhandle = NULL;
65     }
66     return APR_SUCCESS;
67 }
68
69 APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, apr_file_t *file,
70                                           apr_off_t offset, apr_size_t size,
71                                           apr_int32_t flag, apr_pool_t *cont)
72 {
73     static DWORD memblock = 0;
74     DWORD fmaccess = 0;
75     DWORD mvaccess = 0;
76     DWORD offlo;
77     DWORD offhi;
78
79     if (size == 0)
80         return APR_EINVAL;
81     
82     if (flag & APR_MMAP_WRITE)
83         fmaccess |= PAGE_READWRITE;
84     else if (flag & APR_MMAP_READ)
85         fmaccess |= PAGE_READONLY;
86
87     if (flag & APR_MMAP_READ)
88         mvaccess |= FILE_MAP_READ;
89     if (flag & APR_MMAP_WRITE)
90         mvaccess |= FILE_MAP_WRITE;
91
92     if (!file || !file->filehand || file->filehand == INVALID_HANDLE_VALUE
93         || file->buffered)
94         return APR_EBADF;
95
96     if (!memblock)
97     {
98         SYSTEM_INFO si;
99         GetSystemInfo(&si);
100         memblock = si.dwAllocationGranularity;
101     }   
102     
103     *new = apr_pcalloc(cont, sizeof(apr_mmap_t));
104     (*new)->pstart = (offset / memblock) * memblock;
105     (*new)->poffset = offset - (*new)->pstart;
106     (*new)->psize = (apr_size_t)((*new)->poffset) + size;
107     /* The size of the CreateFileMapping object is the current size
108      * of the size of the mmap object (e.g. file size), not the size 
109      * of the mapped region!
110      */
111
112     (*new)->mhandle = CreateFileMapping(file->filehand, NULL, fmaccess,
113                                         0, 0, NULL);
114     if (!(*new)->mhandle || (*new)->mhandle == INVALID_HANDLE_VALUE)
115     {
116         *new = NULL;
117         return apr_get_os_error();
118     }
119
120     offlo = (DWORD)(*new)->pstart;
121     offhi = (DWORD)((*new)->pstart >> 32);
122     (*new)->mv = MapViewOfFile((*new)->mhandle, mvaccess, offhi,
123                                offlo, (*new)->psize);
124     if (!(*new)->mv)
125     {
126         apr_status_t rv = apr_get_os_error();
127         CloseHandle((*new)->mhandle);
128         *new = NULL;
129         return rv;
130     }
131
132     (*new)->mm = (char*)((*new)->mv) + (*new)->poffset;
133     (*new)->size = size;
134     (*new)->cntxt = cont;
135     APR_RING_ELEM_INIT(*new, link);
136
137     /* register the cleanup... */
138     apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
139                          apr_pool_cleanup_null);
140     return APR_SUCCESS;
141 }
142
143 APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
144                                        apr_mmap_t *old_mmap,
145                                        apr_pool_t *p,
146                                        int transfer_ownership)
147 {
148     *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
149     (*new_mmap)->cntxt = p;
150
151     APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
152
153     apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
154                               apr_pool_cleanup_null);
155     return APR_SUCCESS;
156 }
157
158 APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm)
159 {
160     return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup);
161 }
162
163 #endif