Hello Eyal,

Are you looking for a pure Perl way of getting aligned memory, or an XS
approach?

One really hackish, pure Perl way to do what you want is to allocate more
memory than you need---more by a page size---then give an address within
$buffer that aligns to your memory page size, which is probably 64 bytes.
This is far from ideal, but it would work.

How then would you read or modify the contents from Perl? You'd have to use
substr. (I looked for a way to utilize Perl's internal sv_chop C method,
but that only appears to work on very short strings, as documented here:
https://perldoc.perl.org/perlguts.html#Offsets).

use strict;
use warnings;
use Devel::Peek;

my $BUFFER_SIZE = 128;
my $PAGE_SIZE = 64;

# Initial memory allocation
my $buffer = "\0" x ($BUFFER_SIZE + $PAGE_SIZE - 1);
print "=== Initial PV has COW flag set:\n";
Dump($buffer);

# Must modify to remove COW flag
$buffer .= '';
print "=== After appending empty string, we have\n";
Dump($buffer);

# Find offset to use, which is also needed for substr operations
my $c_address = unpack('Q', pack('P', $buffer));
my $bytes_into_page = $c_address % $PAGE_SIZE;
my $offset = $PAGE_SIZE - $bytes_into_page;
printf "=== address is 0x%x, which is %d into a page; use offset of %d\n",
    $c_address, $bytes_into_page, $offset;

# Modify the contents using substr
substr($buffer, $offset, 5) = 'a' x 5;
print "=== After substr, dump gives === \n";
Dump($buffer);

-- David

On Thu, Oct 18, 2018 at 11:39 AM Eyal BenDavid <bde...@gmail.com> wrote:

> Hi all,
>
> A driver exposes its API by ioctl interface.
>
> The argument for the ioctl call is a memory buffer that its address
> must aligned to OS page size.
>
> For example the allocation in C would call valloc (or posix_memalign)
>
> Simple Perl allocation of the buffer like this:
>
>      $buffer = "\0" x  BUFFER_SIZE ;
>
> is not enough since most probably the starting address of the scalar
> wont be aligned to OS page size.
>
> Is there a simple way to achieve this?
>
> Note: I convert the buffer to the C address like this:
>
>      my $c_address = unpack('Q', pack('P', $buffer));
>
> Thanks!
> Eyal
>


-- 
 "Debugging is twice as hard as writing the code in the first place.
  Therefore, if you write the code as cleverly as possible, you are,
  by definition, not smart enough to debug it." -- Brian Kernighan

Reply via email to