File Coverage

blib/lib/vm.pm
Criterion Covered Total %
statement 105 163 64.4
branch 0 42 0.0
condition 0 9 0.0
subroutine 35 45 77.7
pod n/a
total 140 259 54.0


line stmt bran cond sub pod time code
1             package vm;
2             $VERSION = '1.0.1';
3              
4             bootstrap xsub;
5              
6 1         5 use xsub q{
7             #include
8             #include
9 1     1   2741 };
  1         3  
10              
11 1         5 use xsub peek => q($$), q{
12             U8 *pv = (U8 *)SvUV(argv[0]);
13             STRLEN pvl = SvUV(argv[1]);
14             return newSVpv(pvl ? pv : (U8*)"", pvl);
15 1     1   5 };
  1         2  
16            
17 1         3 use xsub poke => q($$), q{
18             U8 *p = (U8 *)SvUV(argv[0]);
19             SV *sv = argv[1];
20             STRLEN pvl;
21             char *pv = SvPV(sv, pvl);
22             if (pvl)
23             Copy(pv, (U8 *)p, pvl, U8);
24             return newSVuv(pvl);
25 1     1   4 };
  1         2  
26            
27 1         4 use xsub malloc => q($), q{
28             UV n = SvUV(argv[0]);
29             void *p;
30             New(0, p, n, U8);
31             return newSVuv((UV)p);
32 1     1   4 };
  1         2  
33              
34 1         3 use xsub calloc => q($), q{
35             UV n = SvUV(argv[0]);
36             void *p;
37             Newz(0, p, n, U8);
38             return newSVuv((UV)p);
39 1     1   4 };
  1         2  
40            
41 1         3 use xsub realloc => q($$), q{
42             void *p = (void *)SvUV(argv[0]);
43             UV n = SvUV(argv[1]);
44             if (!n) {
45             Safefree(p);
46             return newSVuv(0);
47             }
48             Renew(p, n, U8);
49             return newSVuv((UV)p);
50 1     1   4 };
  1         2  
51            
52 1         4 use xsub free => q($), q{
53             void *p = (void *)SvUV(argv[0]);
54             Safefree(p);
55             return &PL_sv_yes;
56 1     1   4 };
  1         1  
57            
58 1         9 use xsub memcpy => q($$$), q{
59             void *p = (void *)SvUV(argv[0]);
60             void *q = (void *)SvUV(argv[1]);
61             UV n = SvUV(argv[2]);
62             if (n)
63             Copy(p, q, n, U8);
64             return newSVuv(n);
65 1     1   9 };
  1         2  
66              
67 1         3 use xsub memmove => q($$$), q{
68             void *p = (void *)SvUV(argv[0]);
69             void *q = (void *)SvUV(argv[1]);
70             UV n = SvUV(argv[2]);
71             if (n)
72             Move(p, q, n, U8);
73             return newSVuv(n);
74 1     1   5 };
  1         1  
75              
76 1         6 use xsub memset => q($$$), q{
77             void *p = (void *)SvUV(argv[0]);
78             UV c = SvUV(argv[1]);
79             UV n = SvUV(argv[2]);
80             if (n)
81             memset(p, c, n);
82             return newSVuv(n);
83 1     1   4 };
  1         1  
84              
85 1         4 use xsub memzero => q($$), q{
86             void *p = (void *)SvUV(argv[0]);
87             UV n = SvUV(argv[1]);
88             if (n)
89             Zero(p, n, U8);
90             return newSVuv(n);
91 1     1   4 };
  1         1  
92              
93 1         3 use xsub memchr => q($$$), q{
94             UV p = SvUV(argv[0]);
95             UV c = SvUV(argv[1]);
96             UV n = SvUV(argv[2]);
97             UV i = n ? (UV)memchr((void *)p, c, n) : 0;
98             return i ? newSVuv(i) : &PL_sv_undef;
99 1     1   4 };
  1         2  
100              
101 1         4 use xsub memmem => q($$$$), q{
102             char *p = (char *)SvUV(argv[0]);
103             UV pn = SvUV(argv[1]);
104             char *q = (char *)SvUV(argv[0]);
105             UV qn = SvUV(argv[1]);
106             UV i = (UV)memmem((void *)p, pn, q, qn);
107             return i ? newSVuv(i) : &PL_sv_undef;
108 1     1   4 };
  1         2  
109              
110 1         4 use xsub memcmp => q($$$), q{
111             UV p = SvUV(argv[0]);
112             UV q = SvUV(argv[1]);
113             UV n = SvUV(argv[2]);
114             UV i = n ? memcmp((void *)p, (void *)q, n) : 0;
115             return newSVuv(i);
116 1     1   5 };
  1         2  
117              
118 1         4 use xsub mlock => q($$), q{
119             UV p = SvUV(argv[0]);
120             UV len = SvUV(argv[1]);
121             return mlock((void *)p, len) ? &PL_sv_undef : &PL_sv_yes;
122 1     1   5 };
  1         2  
123              
124 1         4 use xsub munlock => q($$), q{
125             UV p = SvUV(argv[0]);
126             UV len = SvUV(argv[1]);
127             return munlock((void *)p, len) ? &PL_sv_undef : &PL_sv_yes;
128 1     1   5 };
  1         2  
129              
130 1     1   4 use xsub MCL_CURRENT => q(), q{ return newSVuv(MCL_CURRENT); };
  1         2  
  1         4  
131 1     1   5 use xsub MCL_FUTURE => q(), q{ return newSVuv(MCL_FUTURE); };
  1         2  
  1         3  
132              
133 1         3 use xsub mlockall => q($), q{
134             UV flags = SvUV(argv[0]) & (MCL_CURRENT | MCL_FUTURE);
135             return mlockall(flags) ? &PL_sv_undef : &PL_sv_yes;
136 1     1   5 };
  1         2  
137              
138 1         3 use xsub munlockall => q(), q{
139             return munlockall() ? &PL_sv_undef : &PL_sv_yes;
140 1     1   4 };
  1         2  
141              
142 1     1   5 use xsub PROT_READ => q(), q{ return newSVuv(PROT_READ); };
  1         2  
  1         3  
143 1     1   4 use xsub PROT_WRITE => q(), q{ return newSVuv(PROT_WRITE); };
  1         2  
  1         3  
144 1     1   5 use xsub PROT_EXEC => q(), q{ return newSVuv(PROT_EXEC); };
  1         1  
  1         5  
145 1     1   5 use xsub PROT_NONE => q(), q{ return newSVuv(PROT_NONE); };
  1         1  
  1         5  
146              
147 1     1   5 use xsub MAP_SHARED => q(), q{ return newSVuv(MAP_SHARED); };
  1         2  
  1         5  
148 1     1   5 use xsub MAP_PRIVATE => q(), q{ return newSVuv(MAP_PRIVATE); };
  1         2  
  1         6  
149              
150 1     1   5 use xsub MS_ASYNC => q(), q{ return newSVuv(MS_ASYNC); };
  1         1  
  1         4  
151 1     1   4 use xsub MS_INVALIDATE => q(), q{ return newSVuv(MS_INVALIDATE); };
  1         2  
  1         3  
152 1     1   5 use xsub MS_SYNC => q(), q{ return newSVuv(MS_SYNC); };
  1         21  
  1         5  
153              
154 1         4 use xsub _mmap => q($$$$$$), q{
155             void *q = (void *)SvUV(argv[0]);
156             UV len = SvUV(argv[1]);
157             UV prot = SvUV(argv[2]) & (PROT_READ | PROT_WRITE | PROT_EXEC);
158             UV flags = SvUV(argv[3]) & (MAP_SHARED | MAP_PRIVATE);
159             UV fd = SvUV(argv[4]);
160             UV off = SvUV(argv[5]);
161              
162             void *p = (void *)mmap(q, len, prot, flags, fd, off);
163             return (!p || p == MAP_FAILED) ? &PL_sv_undef : newSVuv((UV)p);
164 1     1   5 };
  1         2  
165              
166 1         3 use xsub _mremap => q($$$$), q{
167             void *q = (void *)SvUV(argv[0]);
168             UV len0 = SvUV(argv[1]);
169             UV len1 = SvUV(argv[2]);
170             UV flags = SvUV(argv[3]) & (MREMAP_MAYMOVE);
171              
172             void *p = (void *)mremap(q, len0, len1, flags);
173             return p ? newSVuv((UV)p) : &PL_sv_undef;
174 1     1   5 };
  1         2  
175              
176 1         4 use xsub _munmap => q($$), q{
177             void *p = (void *)SvUV(argv[0]);
178             UV len = SvUV(argv[1]);
179              
180             return newSViv(munmap(p, len));
181 1     1   6 };
  1         1  
182              
183 1         3 use xsub _mprotect => q($$$), q{
184             void *p = (void *)SvUV(argv[0]);
185             UV len = SvUV(argv[1]);
186             UV prot = SvUV(argv[3]) & (PROT_READ | PROT_WRITE | PROT_EXEC);
187             return mprotect(p, len, prot) ? &PL_sv_undef : &PL_sv_yes;
188 1     1   5 };
  1         2  
189              
190 1         4 use xsub _msync => q($$$), q{
191             UV p = SvUV(argv[0]);
192             UV len = SvUV(argv[1]);
193             UV flags = SvUV(argv[2]) & (MS_ASYNC | MS_INVALIDATE | MS_SYNC);
194              
195             if (msync((void *)p, len, flags))
196             return &PL_sv_undef;
197             return &PL_sv_yes;
198 1     1   5 };
  1         2  
199              
200 1         4 use xsub _getpagesize => q(), q{
201             return newSVuv(getpagesize());
202 1     1   6 };
  1         2  
203              
204             {
205             package vm::mmap;
206              
207             sub TIESCALAR {
208 0     0     my ($p, $ptr, $len, $rptr, $rlen, $prot, $flags, $fp) = @_;
209 0           bless [$ptr, $len, $rptr, $rlen, $prot, $flags, $fp], $p
210             }
211              
212             sub FETCH {
213 0     0     my ($x) = @_;
214 0           my ($ptr, $len, undef, undef, $prot) = @$x;
215 0 0         $prot & &vm::PROT_READ or return undef;
216              
217 0           vm::peek($ptr, $len)
218             }
219              
220             sub STORE {
221 0     0     my ($x, $v) = @_;
222 0           my ($ptr, $len, $rptr, $rlen, $prot, $flags, $fp) = @$x;
223 0 0         $prot & &vm::PROT_WRITE or return undef;
224            
225 0           my $vlen = length($v);
226 0 0         $vlen < $len and $v .= "\0" x ($len - $vlen);
227 0 0         $vlen > $len and substr($v, $len) = '';
228              
229 0           vm::poke($ptr, $v);
230              
231 0           for (select $fp) {
232 0 0         $| and vm::_msync($rptr, $rlen, &vm::MS_SYNC);
233 0           select $_;
234             }
235             }
236              
237             sub DESTROY {
238 0     0     my ($x, $v) = @_;
239 0           my (undef, undef, $rptr, $rlen) = @$x;
240              
241 0           vm::_munmap($rptr, $rlen);
242 0           @$x = ( );
243             }
244             }
245              
246             sub mmap($;$$$$) {
247 0     0     my ($fp, $off, $len, $prot, $flags) = @_;
248            
249 0 0         defined $prot or $prot = &PROT_READ | &PROT_WRITE;
250 0           $prot &= (&PROT_READ | &PROT_WRITE | &PROT_EXEC);
251              
252 0 0         defined $flags or $flags =
    0          
253             ($prot & &PROT_WRITE) ? &MAP_SHARED : &MAP_PRIVATE;
254 0           $flags &= (&MAP_SHARED | &MAP_PRIVATE);
255              
256 0           my $fd = do {
257 0 0 0       if (ref($fp) || ref(\$fp) eq 'GLOB') {
    0 0        
258 0           fileno($fp)
259             } elsif ($fp eq '0' or $fp > 0) {
260 0           $fp
261             } else {
262 0           my $fn = $fp;
263 0           undef $fp;
264 0 0         my $mode = ($prot & &PROT_WRITE) ? '+<' : '<';
265 0 0         open $fp, $mode, $fn or warn("$0: $fn: $!\n"), return undef;
266 0           fileno($fp)
267             }
268 0 0         }; defined $fd or return undef;
269              
270 0 0         defined $off or $off = 0;
271 0 0         defined $len or $len = (stat $fp)[7] - $off;
272            
273 0           my $pagesize = _getpagesize();
274 0           my $pagemask = $pagesize - 1;
275 0           my $roff = $off & ~$pagemask;
276 0           my $rlen = ($len + $off - $roff);
277 0 0         $rlen & $pagemask and $rlen = 1 + ($rlen | $pagemask);
278 0 0         $rlen or $rlen += $pagesize;
279              
280 0           my $rptr = _mmap(0, $rlen, $prot, $flags, $fd, $roff);
281 0 0         defined $rptr or return undef;
282 0           my $ptr += $rptr + $off - $roff;
283              
284 0           tie my $x, 'vm::mmap', $ptr, $len, $rptr, $rlen, $prot, $flags, $fp;
285 0           \$x
286             }
287              
288 0     0     sub mmapr ($$$) { &mmap(@_, &PROT_READ ) }
289 0     0     sub mmaprw ($$$) { &mmap(@_, &PROT_READ|&PROT_WRITE ) }
290 0     0     sub mmaprx ($$$) { &mmap(@_, &PROT_READ|&PROT_EXEC ) }
291 0     0     sub mmaprwx($$$) { &mmap(@_, &PROT_READ|&PROT_WRITE|&PROT_EXEC) }
292              
293             sub mprotect($$) {
294 0     0     my ($x, $prot) = @_;
295              
296 0 0 0       ref($x) and ref($x)->isa('SCALAR') or return undef;
297 0 0         my $mmap = tied($$x) or return undef;
298 0 0         $mmap->isa('vm::mmap') or return undef;
299              
300 0           my (undef, undef, $rptr, $rlen) = @$mmap;
301 0           _mprotect($rptr, $rlen, $prot)
302             }
303              
304             1