summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changes6
-rw-r--r--mmap.c169
-rw-r--r--mmap.html28
-rw-r--r--mmap.rd17
4 files changed, 190 insertions, 30 deletions
diff --git a/Changes b/Changes
new file mode 100644
index 0000000..cc5c763
--- /dev/null
+++ b/Changes
@@ -0,0 +1,6 @@
+
+-- 0.1.2
+
+* fixed some bugs (options & new) (Thanks Joseph McDonald <joe@vpop.net>)
+* added anonymous map
+* added mlock, munlock, etc
diff --git a/mmap.c b/mmap.c
index c3e055b..15027df 100644
--- a/mmap.c
+++ b/mmap.c
@@ -36,7 +36,7 @@ static VALUE mm_cMap;
typedef struct {
MMAP_RETTYPE addr;
int smode, pmode, vscope;
- int advice, frozen;
+ int advice, frozen, lock;
size_t len, real;
size_t size;
off_t offset;
@@ -49,11 +49,13 @@ mm_free(t_mm)
{
if (t_mm->path) {
munmap(t_mm->addr, t_mm->len);
- if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE &&
- truncate(t_mm->path, t_mm->real) == -1) {
- rb_raise(rb_eTypeError, "truncate");
+ if (t_mm->path != (char *)-1) {
+ if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE &&
+ truncate(t_mm->path, t_mm->real) == -1) {
+ rb_raise(rb_eTypeError, "truncate");
+ }
+ free(t_mm->path);
}
- free(t_mm->path);
}
free(t_mm);
}
@@ -84,11 +86,13 @@ mm_unmap(obj)
GetMmap(obj, t_mm, 0);
if (t_mm->path) {
munmap(t_mm->addr, t_mm->len);
- if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE &&
- truncate(t_mm->path, t_mm->real) == -1) {
- rb_raise(rb_eTypeError, "truncate");
+ if (t_mm->path != (char *)-1) {
+ if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE &&
+ truncate(t_mm->path, t_mm->real) == -1) {
+ rb_raise(rb_eTypeError, "truncate");
+ }
+ free(t_mm->path);
}
- free(t_mm->path);
t_mm->path = '\0';
}
return Qnil;
@@ -119,17 +123,17 @@ mm_str(obj, modify)
else {
ret = rb_str_new2("");
}
+ if (modify & MM_MODIFY) {
+ if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap");
+ if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't modify mmap");
+ }
if (t_mm->frozen & MM_FROZEN) ret = rb_obj_freeze(ret);
free(RSTRING(ret)->ptr);
RSTRING(ret)->ptr = t_mm->addr;
RSTRING(ret)->len = t_mm->real;
if (modify & MM_ORIGIN)
RSTRING(ret)->orig = ret;
- if (modify & MM_MODIFY) {
- if (OBJ_FROZEN(ret)) rb_error_frozen("mmap");
- if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify mmap");
- }
return ret;
}
@@ -156,21 +160,21 @@ mm_i_options(arg, obj)
key = rb_obj_as_string(key);
options = RSTRING(key)->ptr;
if (strcmp(options, "length") == 0) {
- t_mm->size == NUM2INT(value);
+ t_mm->size = NUM2INT(value);
if (t_mm->size <= 0) {
rb_raise(rb_eArgError, "Invalid value for length %d", t_mm->size);
}
t_mm->frozen |= MM_FIXED;
}
else if (strcmp(options, "offset") == 0) {
- t_mm->offset == NUM2INT(value);
+ t_mm->offset = NUM2INT(value);
if (t_mm->offset < 0) {
rb_raise(rb_eArgError, "Invalid value for offset %d", t_mm->offset);
}
t_mm->frozen |= MM_FIXED;
}
else if (strcmp(options, "advice") == 0) {
- t_mm->advice == NUM2INT(value);
+ t_mm->advice = NUM2INT(value);
}
return Qnil;
}
@@ -195,8 +199,26 @@ mm_map(argc, argv, obj)
argc--;
}
rb_scan_args(argc, argv, "12", &fname, &vmode, &scope);
+ vscope = 0;
+#ifdef MAP_ANON
+ if (NIL_P(fname)) {
+ vscope = MAP_ANON;
+ path = 0;
+ }
+ else {
+ Check_SafeStr(fname);
+ path = RSTRING(fname)->ptr;
+ if (!NIL_P(scope)) {
+ vscope = NUM2INT(scope);
+ if (vscope & MAP_ANON) {
+ rb_raise(rb_eArgError, "filename specified for an anonymous map");
+ }
+ }
+ }
+#else
Check_SafeStr(fname);
path = RSTRING(fname)->ptr;
+#endif
mode = NIL_P(vmode) ? "r" : STR2CSTR(vmode);
if (strcmp(mode, "r") == 0) {
smode = O_RDONLY;
@@ -213,27 +235,42 @@ mm_map(argc, argv, obj)
else {
rb_raise(rb_eArgError, "Invalid mode %s", mode);
}
- vscope = NIL_P(scope) ? MAP_SHARED : NUM2INT(scope);
- if ((fd = open(path, smode)) == -1) {
- rb_raise(rb_eArgError, "Can't open %s", path);
+ vscope |= NIL_P(scope) ? MAP_SHARED : NUM2INT(scope);
+ size = 0;
+ if (path) {
+ if ((fd = open(path, smode)) == -1) {
+ rb_raise(rb_eArgError, "Can't open %s", path);
+ }
+ if (fstat(fd, &st) == -1) {
+ rb_raise(rb_eArgError, "Can't stat %s", path);
+ }
+ size = st.st_size;
}
- if (fstat(fd, &st) == -1) {
- rb_raise(rb_eArgError, "Can't stat %s", path);
+ else {
+ fd = -1;
}
- res = Data_Make_Struct(mm_cMap, mm_mmap, 0, mm_free, t_mm);
- size = st.st_size;
+ res = Data_Make_Struct(obj, mm_mmap, 0, mm_free, t_mm);
offset = 0;
if (options != Qnil) {
rb_iterate(rb_each, options, mm_i_options, res);
if ((t_mm->size + t_mm->offset) > st.st_size) {
- rb_raise(rb_eArgError, "invalid value for size (%d) or offset (%d)",
+ rb_raise(rb_eArgError, "invalid value for length (%d) or offset (%d)",
t_mm->size, t_mm->offset);
}
if (t_mm->size) size = t_mm->size;
offset = t_mm->offset;
}
+ if (!path) {
+ if (size <= 0) {
+ rb_raise(rb_eArgError, "length not specified for an anonymous map");
+ }
+ if (offset) {
+ rb_warning("Ignoring offset for an anonymous map");
+ offset = 0;
+ }
+ }
addr = mmap(0, size, pmode, vscope, fd, offset);
- close(fd);
+ if (fd != -1) close(fd);
if (addr == MAP_FAILED || !addr) {
rb_raise(rb_eArgError, "mmap failed (%x)", addr);
}
@@ -245,7 +282,7 @@ mm_map(argc, argv, obj)
t_mm->pmode = pmode;
t_mm->vscope = vscope;
t_mm->smode = smode;
- t_mm->path = ruby_strdup(path);
+ t_mm->path = (path)?ruby_strdup(path):(char *)-1;
if (smode == O_RDONLY) {
res = rb_obj_freeze(res);
t_mm->frozen |= MM_FROZEN;
@@ -287,13 +324,16 @@ mm_expandf(t_mm, len)
rb_raise(rb_eIOError, "Can't truncate %s", t_mm->path);
}
t_mm->addr = mmap(0, len, t_mm->pmode, t_mm->vscope, fd, t_mm->offset);
+ close(fd);
if (t_mm->addr == MAP_FAILED) {
rb_raise(rb_eArgError, "mmap failed");
}
if (t_mm->advice && madvise(t_mm->addr, len, t_mm->advice) == -1) {
rb_raise(rb_eArgError, "madvise(%d)", errno);
}
- close(fd);
+ if (t_mm->lock && mlock(t_mm->addr, len) == -1) {
+ rb_raise(rb_eArgError, "mlock(%d)", errno);
+ }
t_mm->len = len;
}
@@ -1166,6 +1206,61 @@ mm_undefined(argc, argv, obj)
rb_raise(rb_eNameError, "not yet implemented");
}
+static VALUE
+mm_mlockall(obj, flag)
+ VALUE obj, flag;
+{
+ if (mlockall(NUM2INT(flag)) == -1) {
+ rb_raise(rb_eArgError, "mlockall(%d)", errno);
+ }
+ return Qnil;
+}
+
+static VALUE
+mm_munlockall(obj)
+ VALUE obj;
+{
+ if (munlockall() == -1) {
+ rb_raise(rb_eArgError, "munlockall(%d)", errno);
+ }
+ return Qnil;
+}
+
+static VALUE
+mm_mlock(obj)
+ VALUE obj;
+{
+ mm_mmap *t_mm;
+
+ Data_Get_Struct(obj, mm_mmap, t_mm);
+ if (t_mm->lock) {
+ return obj;
+ }
+ if (mlock(t_mm->addr, t_mm->len) == -1) {
+ rb_raise(rb_eArgError, "mlock(%d)", errno);
+ }
+ t_mm->lock = 1;
+ return obj;
+}
+
+static VALUE
+mm_munlock(obj)
+ VALUE obj;
+{
+ mm_mmap *t_mm;
+
+ Data_Get_Struct(obj, mm_mmap, t_mm);
+ if (!t_mm->lock) {
+ return obj;
+ }
+ if (munlock(t_mm->addr, t_mm->len) == -1) {
+ rb_raise(rb_eArgError, "munlock(%d)", errno);
+ }
+ t_mm->lock = 0;
+ return obj;
+}
+
+
void
Init_mmap()
{
@@ -1205,9 +1300,21 @@ Init_mmap()
#ifdef MAP_ANONYMOUS
rb_define_const(mm_cMap, "MAP_ANONYMOUS", INT2FIX(MAP_ANONYMOUS));
#endif
+#ifdef MAP_NOSYNC
+ rb_define_const(mm_cMap, "MAP_NOSYNC", INT2FIX(MAP_NOSYNC));
+#endif
+ rb_define_const(mm_cMap, "MCL_CURRENT", INT2FIX(MCL_CURRENT));
+ rb_define_const(mm_cMap, "MCL_FUTURE", INT2FIX(MCL_FUTURE));
+
rb_include_module(mm_cMap, rb_mComparable);
rb_include_module(mm_cMap, rb_mEnumerable);
+
rb_define_singleton_method(mm_cMap, "new", mm_map, -1);
+ rb_define_singleton_method(mm_cMap, "mlockall", mm_mlockall, 1);
+ rb_define_singleton_method(mm_cMap, "lockall", mm_mlockall, 1);
+ rb_define_singleton_method(mm_cMap, "munlockall", mm_munlockall, 0);
+ rb_define_singleton_method(mm_cMap, "unlockall", mm_munlockall, 0);
+
rb_define_method(mm_cMap, "unmap", mm_unmap, 0);
rb_define_method(mm_cMap, "munmap", mm_unmap, 0);
rb_define_method(mm_cMap, "msync", mm_msync, -1);
@@ -1216,6 +1323,12 @@ Init_mmap()
rb_define_method(mm_cMap, "mprotect", mm_mprotect, 1);
rb_define_method(mm_cMap, "protect", mm_mprotect, 1);
rb_define_method(mm_cMap, "madvise", mm_madvise, 1);
+ rb_define_method(mm_cMap, "advise", mm_madvise, 1);
+ rb_define_method(mm_cMap, "mlock", mm_mlock, 0);
+ rb_define_method(mm_cMap, "lock", mm_mlock, 0);
+ rb_define_method(mm_cMap, "munlock", mm_munlock, 0);
+ rb_define_method(mm_cMap, "unlock", mm_munlock, 0);
+
rb_define_method(mm_cMap, "extend", mm_extend, 1);
rb_define_method(mm_cMap, "freeze", mm_freeze, 1);
rb_define_method(mm_cMap, "clone", mm_undefined, -1);
diff --git a/mmap.html b/mmap.html
index a0fb98f..eaac054 100644
--- a/mmap.html
+++ b/mmap.html
@@ -31,6 +31,13 @@ Object
<H2><A NAME="label:4">Class Methods
</A></H2><!-- RDLabel: "Class Methods" -->
<DL>
+<DT><A NAME="lockall"><CODE>lockall(<var>flag</var>)</CODE></A><!-- RDLabel: "lockall" -->
+<DD>
+<P>
+disable paging of all pages mapped. <VAR>flag</VAR> can be
+<VAR>Mmap::MCL_CURRENT</VAR> or <VAR>Mmap::MCL_FUTURE</VAR>
+</P>
+</DD>
<DT><A NAME="new"><CODE>new(<var>file</var>, [<var>mode</var> [, <var>protection</var> [, <var>options</var>]]])</CODE></A><!-- RDLabel: "new" -->
<DD>
<P>
@@ -42,7 +49,8 @@ create a new object
</A><!-- RDLabel: "file" -->
<DD>
<P>
-Pathname of the file
+Pathname of the file, if <VAR>nil</VAR> is given an anonymous map
+is created <VAR>Mmanp::MAP_ANON</VAR>
</P>
</DD>
<DT><A NAME="label:8"><VAR>mode</VAR>
@@ -114,6 +122,12 @@ The type of the access (see #madvise)
</DD>
</DL>
</DD>
+<DT><A NAME="unlockall"><CODE>unlockall</CODE></A><!-- RDLabel: "unlockall" -->
+<DD>
+<P>
+reenable paging
+</P>
+</DD>
</DL>
<H2><A NAME="label:5">Methods
</A></H2><!-- RDLabel: "Methods" -->
@@ -138,6 +152,12 @@ add <VAR>count</VAR> bytes to the file (i.e. pre-extend the file)
change the mode, value must be "r", "w" or "rw"
</P>
</DD>
+<DT><A NAME="mlock"><CODE>mlock</CODE></A><!-- RDLabel: "mlock" -->
+<DD>
+<P>
+disable paging
+</P>
+</DD>
<DT><A NAME="msync"><CODE>msync</CODE></A><!-- RDLabel: "msync" -->
<DT><A NAME="flush"><CODE>flush</CODE></A><!-- RDLabel: "flush" -->
<DD>
@@ -145,6 +165,12 @@ change the mode, value must be "r", "w" or "rw"
flush the file
</P>
</DD>
+<DT><A NAME="munlock"><CODE>munlock</CODE></A><!-- RDLabel: "munlock" -->
+<DD>
+<P>
+reenable paging
+</P>
+</DD>
<DT><A NAME="munmap"><CODE>munmap</CODE></A><!-- RDLabel: "munmap" -->
<DD>
<P>
diff --git a/mmap.rd b/mmap.rd
index e7a2ad0..d73f2b2 100644
--- a/mmap.rd
+++ b/mmap.rd
@@ -19,11 +19,16 @@ Object
== Class Methods
+--- lockall(flag)
+ disable paging of all pages mapped. ((|flag|)) can be
+ ((|Mmap::MCL_CURRENT|)) or ((|Mmap::MCL_FUTURE|))
+
--- new(file, [mode [, protection [, options]]])
create a new object
: ((|file|))
- Pathname of the file
+ Pathname of the file, if ((|nil|)) is given an anonymous map
+ is created ((|Mmanp::MAP_ANON|))
: ((|mode|))
Mode to open the file, it can be "r", "w" or "rw"
@@ -54,6 +59,10 @@ Object
: ((|advice|))
The type of the access (see #madvise)
+
+--- unlockall
+ reenable paging
+
== Methods
--- extend(count)
@@ -67,10 +76,16 @@ Object
--- mprotect(mode)
change the mode, value must be "r", "w" or "rw"
+--- mlock
+ disable paging
+
--- msync
--- flush
flush the file
+--- munlock
+ reenable paging
+
--- munmap
terminate the association