New PHP5 APC - version 3.0.19, using PHP5 5.2.0-8+etch11,
[php5-apc.git] / apc_mmap.c
1 /*
2   +----------------------------------------------------------------------+
3   | APC                                                                  |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 2008 The PHP Group                                     |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
16   +----------------------------------------------------------------------+
17
18    This software was contributed to PHP by Community Connect Inc. in 2002
19    and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
20    Future revisions and derivatives of this source code must acknowledge
21    Community Connect Inc. as the original contributor of this module by
22    leaving this note intact in the source code.
23
24    All other licensing and usage conditions are those of the PHP Group.
25
26  */
27
28 /* $Id: apc_mmap.c,v 3.7.2.2 2008/05/11 18:57:00 rasmus Exp $ */
29
30 #include "apc.h"
31
32 #if APC_MMAP
33
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/mman.h>
37
38 /* 
39  * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
40  * tells whatever update daemons might be running to not flush dirty
41  * vm pages to disk unless absolutely necessary.  My guess is that
42  * most systems that don't have this probably default to only synching
43  * to disk when absolutely necessary.
44  */
45 #ifndef MAP_NOSYNC
46 #define MAP_NOSYNC 0
47 #endif
48
49 void *apc_mmap(char *file_mask, size_t size)
50 {
51     void* shmaddr;  /* the shared memory address */
52
53     /* If no filename was provided, do an anonymous mmap */
54     if(!file_mask || (file_mask && !strlen(file_mask))) {
55         shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
56     } else {
57         int fd;
58
59         /* 
60          * If the filemask contains .shm we try to do a POSIX-compliant shared memory
61          * backed mmap which should avoid synchs on some platforms.  At least on
62          * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
63          * a file in a mounted shmfs.  For this to work on Linux you need to make sure
64          * you actually have shmfs mounted.  Also on Linux, make sure the file_mask you
65          * pass in has a leading / and no other /'s.  eg.  /apc.shm.XXXXXX
66          * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
67          * path you want here.
68          */
69         if(strstr(file_mask,".shm")) {
70             mktemp(file_mask);
71             fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
72             if(fd == -1) {
73                 apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
74                 return (void *)-1;
75             }
76             if (ftruncate(fd, size) < 0) {
77                 close(fd);
78                 shm_unlink(file_mask);
79                 apc_eprint("apc_mmap: ftruncate failed:");
80                 return (void *)-1;
81             }
82             shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
83             shm_unlink(file_mask);
84             close(fd);
85         }
86         /*
87          * Support anonymous mmap through the /dev/zero interface as well
88          */
89         else if(!strcmp(file_mask,"/dev/zero")) {
90             fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
91             if(fd == -1) {
92                 apc_eprint("apc_mmap: open on /dev/zero failed:");
93                 return (void *)-1;
94             }
95             shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
96             close(fd);
97         }
98         /* 
99          * Otherwise we do a normal filesystem mmap
100          */
101         else {
102             fd = mkstemp(file_mask);
103             if(fd == -1) {
104                 apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
105                 return (void *)-1;
106             }
107             if (ftruncate(fd, size) < 0) {
108                 close(fd);
109                 unlink(file_mask);
110                 apc_eprint("apc_mmap: ftruncate failed:");
111             }
112             shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
113             close(fd);
114             unlink(file_mask);
115         }
116     }
117     if((long)shmaddr == -1) {
118         apc_eprint("apc_mmap: mmap failed:");
119     }
120     return shmaddr;
121 }
122
123 void apc_unmap(void* shmaddr, size_t size)
124 {
125     if (munmap(shmaddr, size) < 0) {
126         apc_wprint("apc_unmap: munmap failed:");
127     }
128 }
129
130 #endif
131
132 /*
133  * Local variables:
134  * tab-width: 4
135  * c-basic-offset: 4
136  * End:
137  * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
138  * vim<600: expandtab sw=4 ts=4 sts=4
139  */