2 * ex: set ts=8 sts=4 sw=4 et:
5 #define PERL_NO_GET_CONTEXT
10 #if defined(PERLIO_LAYERS) && defined(HAS_MMAP)
16 * mmap as "buffer" layer
20 PerlIOBuf base; /* PerlIOBuf stuff */
21 Mmap_t mptr; /* Mapped address */
22 Size_t len; /* mapped length */
23 STDCHAR *bbuf; /* malloced buffer if map fails */
27 PerlIOMmap_map(pTHX_ PerlIO *f)
30 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
31 const IV flags = PerlIOBase(f)->flags;
35 if (flags & PERLIO_F_CANREAD) {
36 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
38 const int fd = PerlIO_fileno(f);
40 SETERRNO(EBADF,RMS_IFI);
43 code = Fstat(fd, &st);
44 if (code == 0 && S_ISREG(st.st_mode)) {
45 SSize_t len = st.st_size - b->posn;
48 if (PL_mmap_page_size <= 0)
49 Perl_croak(aTHX_ "panic: bad pagesize %" IVdf,
53 * This is a hack - should never happen - open should
56 b->posn = PerlIO_tell(PerlIONext(f));
58 posn = (b->posn / PL_mmap_page_size) * PL_mmap_page_size;
59 len = st.st_size - posn;
60 m->mptr = (Mmap_t)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
61 if (m->mptr && m->mptr != (Mmap_t) - 1) {
62 #if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
63 madvise(m->mptr, len, MADV_SEQUENTIAL);
65 #if 0 && defined(HAS_MADVISE) && defined(MADV_WILLNEED)
66 madvise(m->mptr, len, MADV_WILLNEED);
68 PerlIOBase(f)->flags =
69 (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF;
70 b->end = ((STDCHAR *) m->mptr) + len;
71 b->buf = ((STDCHAR *) m->mptr) + (b->posn - posn);
80 PerlIOBase(f)->flags =
81 flags | PERLIO_F_EOF | PERLIO_F_RDBUF;
83 b->ptr = b->end = b->ptr;
92 PerlIOMmap_unmap(pTHX_ PerlIO *f)
94 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
97 PerlIOBuf * const b = &m->base;
99 /* The munmap address argument is tricky: depending on the
100 * standard it is either "void *" or "caddr_t" (which is
101 * usually "char *" (signed or unsigned). If we cast it
102 * to "void *", those that have it caddr_t and an uptight
103 * C++ compiler, will freak out. But casting it as char*
104 * should work. Maybe. (Using Mmap_t figured out by
105 * Configure doesn't always work, apparently.) */
106 code = munmap((char*)m->mptr, m->len);
110 if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) != 0)
113 b->ptr = b->end = b->buf;
114 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
120 PerlIOMmap_get_base(pTHX_ PerlIO *f)
122 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
123 PerlIOBuf * const b = &m->base;
124 if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
126 * Already have a readbuffer in progress
132 * We have a write buffer or flushed PerlIOBuf read buffer
134 m->bbuf = b->buf; /* save it in case we need it again */
135 b->buf = NULL; /* Clear to trigger below */
138 PerlIOMmap_map(aTHX_ f); /* Try and map it */
141 * Map did not work - recover PerlIOBuf buffer if we have one
146 b->ptr = b->end = b->buf;
149 return PerlIOBuf_get_base(aTHX_ f);
153 PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
155 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
156 PerlIOBuf * const b = &m->base;
157 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
159 if (b->ptr && (b->ptr - count) >= b->buf
160 && memEQ(b->ptr - count, vbuf, count)) {
162 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
167 * Loose the unwritable mapped buffer
171 * If flush took the "buffer" see if we have one from before
173 if (!b->buf && m->bbuf)
176 PerlIOBuf_get_base(aTHX_ f);
180 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
184 PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
186 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
187 PerlIOBuf * const b = &m->base;
189 if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
191 * No, or wrong sort of, buffer
194 if (PerlIOMmap_unmap(aTHX_ f) != 0)
198 * If unmap took the "buffer" see if we have one from before
200 if (!b->buf && m->bbuf)
203 PerlIOBuf_get_base(aTHX_ f);
207 return PerlIOBuf_write(aTHX_ f, vbuf, count);
211 PerlIOMmap_flush(pTHX_ PerlIO *f)
213 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
214 PerlIOBuf * const b = &m->base;
215 IV code = PerlIOBuf_flush(aTHX_ f);
217 * Now we are "synced" at PerlIOBuf level
224 if (PerlIOMmap_unmap(aTHX_ f) != 0)
229 * We seem to have a PerlIOBuf buffer which was not mapped
230 * remember it in case we need one later
239 PerlIOMmap_fill(pTHX_ PerlIO *f)
241 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
242 IV code = PerlIO_flush(f);
243 if (code == 0 && !b->buf) {
244 code = PerlIOMmap_map(aTHX_ f);
246 if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
247 code = PerlIOBuf_fill(aTHX_ f);
253 PerlIOMmap_close(pTHX_ PerlIO *f)
255 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
256 PerlIOBuf * const b = &m->base;
257 IV code = PerlIO_flush(f);
261 b->ptr = b->end = b->buf;
263 if (PerlIOBuf_close(aTHX_ f) != 0)
269 PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
271 return PerlIOBase_dup(aTHX_ f, o, param, flags);
275 PERLIO_FUNCS_DECL(PerlIO_mmap) = {
276 sizeof(PerlIO_funcs),
279 PERLIO_K_BUFFERED|PERLIO_K_RAW,
283 PerlIOBase_binmode, /* binmode */
298 PerlIOBase_setlinebuf,
303 PerlIOBuf_set_ptrcnt,
306 #endif /* Layers available */
308 MODULE = PerlIO::mmap PACKAGE = PerlIO::mmap
314 #if defined(PERLIO_LAYERS) && defined(HAS_MMAP)
315 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_mmap));