[Vm-dev] external addresses and callbacks (FFI+Alien merge)

Ryan Macnak rmacnak at gmail.com
Fri Sep 18 03:55:13 UTC 2015


On Tue, Sep 15, 2015 at 8:29 AM, Esteban Lorenzano <estebanlm at gmail.com>
wrote:

>
> Hi,
>
> I’m working on merge FFI with Alien as a way to provide a single callback
> mechanism (I already talked with Eliot and he agrees this is the way to go
> in the future).
> That means review certain stuff, a couple of them I already submitted in
> my last commit.
> Now I have this problem. This is my example method:
>
> exampleCqsort
>         | cb rand values orig sort |
>
>         rand := Random new.
>         values := FFIExternalArray newType: 'double' size: 100.
>         1 to: 100 do: [ :i| values at: i put: rand next ].
>         orig := (1 to: 100) collect: [:i| values at: i].
>         cb := Callback
>                 signature:  #(int (*)(const void *, const void *))
>                 block: [ :arg1 :arg2 | ((arg1 doubleAt: 1) - (arg2
> doubleAt: 1)) sign ].
>         [
>                 self primQsort: values getHandle with: 100 with: values
> type typeSize with: cb thunk.
>                 sort := values asArray ]
>         ensure: [ values free ].
>         ^orig -> sort
>
> primQsort: array with: count with: size with: compare
>         <cdecl: void 'qsort' (void* ulong ulong void*) module: 'libc’>
>         ^ self primitiveFailed
>
> … that basically works. But this depends on this method in Callback:
>
> voidstarvoidstarRetint: callbackContext sp: spAlien
>         <signature: #(int (*)(const void *, const void *)) abi: 'IA32'>
>         | value |
>
>         value := block
>                         value: (Alien forPointer: (spAlien unsignedLongAt:
> 1))
>                         value: (Alien forPointer: (spAlien unsignedLongAt:
> 5)).
>         ^ callbackContext wordResult: value
>
> And I want to remove Alien from the equation (there will still be some…
> and there will be the primitives of course, but I want to reduce their use
> at the minimum for obvious reasons: hide the extra complexity to users).
> So this function would be something like this instead:
>
> voidstarvoidstarRetint: callbackContext sp: spAlien
>         <signature: #(int (*)(const void *, const void *)) abi: 'IA32'>
>         | value |
>
>         value := block
>                         value: (spAlien pointerAt: 1) “It will answer an
> ExternalAddress”
>                         value: ((spAlien pointerAt: 5). “It will answer an
> ExternalAddress”
>         ^ callbackContext wordResult: value
>
>  So… this *should* work but it doesn’t because in primitiveFFIDoubleAt: I
> have a call to
>
> ffiAddressOf: rcvr startingAt: byteOffset size: byteSize
>
> who mades this check:
>
>                 "don't you dare to read from object memory!"
>                 (addr == 0 or:[interpreterProxy isInMemory: addr])
>                         ifTrue:[^interpreterProxy primitiveFail].
>
> and well… since I’m calling things from a callback the #isInMemory: method
> fails.
>
> If I took out that method everything works ok and since the equivalent
> IA32ABIPlugin does not have that check I can suppose it is ok to remove the
> validation.
>
> But! Since there was that comment ("don't you dare to read from object
> memory!”)… I’m afraid I can be making a mistake.
>
> What do you think?


The elements of your FFIExternalArray should be in malloc's heap, not in
the Smalltalk heap, so the check should pass.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20150917/d6262da4/attachment.htm


More information about the Vm-dev mailing list