IPC-Mmap

 view release on metacpan or  search on metacpan

Mmap.xs  view on Meta::CPAN

			    errno = ENOENT;
			    return 0;
#endif
			}
			if (strEQ(name, "MAP_SHARED")) {
#ifdef MAP_SHARED
				return MAP_SHARED;
#else
			    errno = ENOENT;
			    return 0;
#endif
			}

		case 'P':
			if (strEQ(name, "PROT_READ")) {
#ifdef PROT_READ
				return PROT_READ;
#else
			    errno = ENOENT;
			    return 0;
#endif
			}
			if (strEQ(name, "PROT_WRITE")) {
#ifdef PROT_WRITE
				return PROT_WRITE;
#else
			    errno = ENOENT;
			    return 0;
#endif
			}

		default:
			break;
	}
    errno = EINVAL;
    return 0;
}

static size_t pagesize;

#endif	/* not Win32 */

MODULE = IPC::Mmap		PACKAGE = IPC::Mmap

double
constant(name,arg)
	char *		name
	int		arg

# read len bytes starting at off from mmap's region defined
# by addr, into the Perl scalar var returns the actual length read

void
mmap_read(addr, maxlen, off, var, len)
	SV *    addr
	size_t        maxlen
	int         off
	SV *          var
	size_t        len
    PROTOTYPE: $$$$$
    PPCODE:
        UV tmp = SvUV(addr);
	    caddr_t lcladdr = INT2PTR(caddr_t, (tmp + off));

		if (len > maxlen - off)
			len = maxlen - off;
#		printf("\nmmap_read: length is %i\n", len);
		sv_setpvn(var, lcladdr, len);
		SvSETMAGIC(var);
		ST(0) = sv_2mortal(newSVnv(len));
		XSRETURN(1);

# write len bytes starting at off from mmap's region defined
# by addr, from the Perl scalar var. If no len
# specified, writes complete length of var; if length of
# var is < len, then only writes var's length; if len of
# var length exceeds the mmaped region length,
# only the allowable length will be written
# returns the number of bytes actually written

void
mmap_write(addr, maxlen, off, var, len)
	SV *  addr
	int   maxlen
	int   off
	SV * var
	int   len
    PROTOTYPE: $$$$$
    PPCODE:
        UV tmp = SvUV(addr);
	    caddr_t lcladdr = INT2PTR(caddr_t, (tmp + off));
 		STRLEN varlen;
 		char * ptr;

#		printf("\nmmap_write: addr %p maxlen %i off %i len %i\n",
#			lcladdr, maxlen, off, len);

		ptr = SvPV(var, varlen);
		if (len > (int)varlen)
			len = varlen;
		if (len > (maxlen - off))
			len = maxlen - off;
#		printf("\n lcladdr is %p offset is %d length is %d ptr is %p\n", addr, off, len, ptr);
#		printf("\ncopying memory\n");
#		dest = (char *)(lcladdr + off);
		memcpy(lcladdr, ptr, len);
#		dest[len] = (char)0;
# 		printf("\nmemory copied\n");
#		printf("\n%s\n", dest);
		ST(0) = sv_2mortal(newSVnv((int) len));
		XSRETURN(1);

#ifndef WIN32

MODULE = IPC::Mmap		PACKAGE = IPC::Mmap::POSIX

double
constant(name,arg)
	char *		name
	int		arg

void
_mmap_anon(len, prot, flags)
	size_t        len
	int           prot
	int           flags
    PROTOTYPE: $$$
    PPCODE:
		int   fd;
		void *  addr;
		int   slop;
/*		struct stat st; */

#		printf("\n_mmap: len %i prot %i flags %i\n", len, prot, flags);
 		EXTEND(SP, 3);
		fd = -1;
		if (!len)  {
			croak("mmap: MAP_ANON specified, but no length specified. cannot infer length from file");
			PUSHs(&PL_sv_undef);
			PUSHs(&PL_sv_undef);
			PUSHs(&PL_sv_undef);
			XSRETURN(3);
		}

		if (pagesize == 0) {
			pagesize = getpagesize();
		}

#		slop = off % pagesize;
		slop = 0;

#		addr = mmap(0, len + slop, prot, flags, fd, off - slop);
		addr = mmap(0, len + slop, prot, flags, fd, 0);

#		printf("\n_mmap: fileno %i slop %i addr %u\n", fd, slop, addr);

		if (addr == NULL) {
			croak("mmap: mmap call failed: errno: %d errmsg: %s ", errno, strerror(errno));
		 	PUSHs(&PL_sv_undef);
		 	PUSHs(&PL_sv_undef);
		 	PUSHs(&PL_sv_undef);
			XSRETURN(3);
		}
#
# return the address, the length (incl slop),
# and the offset (adjusted to nearest page)
#
	 	PUSHs(sv_2mortal(newSVuv(PTR2UV(addr))));
	 	PUSHs(sv_2mortal(newSVnv((int) len + slop)));
	 	PUSHs(sv_2mortal(newSVnv((int) slop)));
		XSRETURN(3);

void
_mmap(len, prot, flags, fh)
	size_t        len
	int           prot
	int           flags
	FILE *        fh
    PROTOTYPE: $$$*
    PPCODE:
		int   fd;
		void *  addr;
		int   slop;
		struct stat st;

#		printf("\n_mmap: len %i prot %i flags %i\n", len, prot, flags);
 		EXTEND(SP, 3);
		if (flags&MAP_ANON) {
			fd = -1;
			if (!len)  {
				croak("mmap: MAP_ANON specified, but no length specified. cannot infer length from file");
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
				XSRETURN(3);
			}
		}
		else {
			fd = fileno(fh);
			if (fd < 0) {
				croak("mmap: file not open or does not have associated fileno");
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
				XSRETURN(3);
			}
			if (fstat(fd, &st) == -1) {
				croak("mmap: no len provided, fstat failed, unable to infer length");
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
				XSRETURN(3);
			}
			if (!len) {
				len = st.st_size;
			}
			else if (len > st.st_size) {
				croak("_mmap: file size %i too small for specified length %i", st.st_size, len);
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
			 	PUSHs(&PL_sv_undef);
				XSRETURN(3);
			}
#			printf("\n_mmap: fileno %i len %i\n", fd, len);
		}

		if (pagesize == 0) {
			pagesize = getpagesize();
		}

#		slop = off % pagesize;
		slop = 0;

#		addr = mmap(0, len + slop, prot, flags, fd, off - slop);
		addr = mmap(0, len + slop, prot, flags, fd, 0);

#		printf("\n_mmap: fileno %i slop %i addr %u\n", fd, slop, addr);

		if (addr == NULL) {
			croak("mmap: mmap call failed: errno: %d errmsg: %s ", errno, strerror(errno));
		 	PUSHs(&PL_sv_undef);
		 	PUSHs(&PL_sv_undef);
		 	PUSHs(&PL_sv_undef);
			XSRETURN(3);
		}
#
# return the address, the length (incl slop),
# and the offset (adjusted to nearest page)
#
	 	PUSHs(sv_2mortal(newSVuv(PTR2UV(addr))));
	 	PUSHs(sv_2mortal(newSVnv((int) len + slop)));
	 	PUSHs(sv_2mortal(newSVnv((int) slop)));
		XSRETURN(3);

void
_munmap(addr, len)
	void *    addr
	size_t    len
    PROTOTYPE: $$
    PPCODE:
#
# XXX refrain from dumping core if this
# var wasnt previously mmap'd
#
#		printf("_munmap: addr %p len %i\n", addr, len);
		if (munmap(addr, len) == -1) {
#			printf("_munmap failed! errno %d\n", errno);
			croak("munmap failed! errno %d %s\n", errno, strerror(errno));
			ST(0) = &PL_sv_undef;
		}
		else
			ST(0)  = &PL_sv_yes;
#		printf("leaving _munmap\n");
		XSRETURN(1);

#endif



( run in 3.096 seconds using v1.01-cache-2.11-cpan-71847e10f99 )