This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new a0206ec  fix: go's atomic operations require 64bit alignment in 
structs on ARM (#323)
a0206ec is described below

commit a0206ec757ff7bcb02cee332852ac3e2e7eeaa3a
Author: Chris Pahl <[email protected]>
AuthorDate: Fri Mar 21 19:30:33 2025 +0100

    fix: go's atomic operations require 64bit alignment in structs on ARM (#323)
    
    ### Rationale for this change
    
    I've tried to run a pqarrow based writer/reader on a RaspberryPi. This
    lead to an almost immediate crash however, due to an unaligned struct
    member in `ipc.Reader`.
    
    I did not check yet if there are other structs that might have similar
    issues. It would probably be nice to
    
    ### What changes are included in this PR?
    
    Swapping the struct field order is enough to fix the issue. See also the
    link in the diff.
    
    ### Are these changes tested?
    
    Yes, no additional unit tests due to hardware constraints, but my
    program runs through now.
    
    ### Are there any user-facing changes?
    
    Less crashing?
    
    ### Other note
    
    I noticed that this will also crash if I do not pass the `noasm` build
    tag, which is probably also a little unfortunate. This seems to be
    because the `funclist` in `parquet/internal/bmi/bmi.go` is empty. If you
    want I can add a default, so the funclist is always initialized with the
    fallback go implementation, unless overwritten.
---
 arrow/ipc/reader.go         | 15 +++++++--------
 parquet/internal/bmi/bmi.go | 10 ++++++++--
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/arrow/ipc/reader.go b/arrow/ipc/reader.go
index 2a4f859..1934c71 100644
--- a/arrow/ipc/reader.go
+++ b/arrow/ipc/reader.go
@@ -39,7 +39,7 @@ type Reader struct {
        r      MessageReader
        schema *arrow.Schema
 
-       refCount int64
+       refCount atomic.Int64
        rec      arrow.Record
        err      error
 
@@ -70,13 +70,14 @@ func NewReaderFromMessageReader(r MessageReader, opts 
...Option) (reader *Reader
 
        rr := &Reader{
                r:        r,
-               refCount: 1,
+               refCount: atomic.Int64{},
                // types:    make(dictTypeMap),
                memo:               dictutils.NewMemo(),
                mem:                cfg.alloc,
                ensureNativeEndian: cfg.ensureNativeEndian,
                expectedSchema:     cfg.schema,
        }
+       rr.refCount.Add(1)
 
        if !cfg.noAutoSchema {
                if err := rr.readSchema(cfg.schema); err != nil {
@@ -141,16 +142,16 @@ func (r *Reader) readSchema(schema *arrow.Schema) error {
 // Retain increases the reference count by 1.
 // Retain may be called simultaneously from multiple goroutines.
 func (r *Reader) Retain() {
-       atomic.AddInt64(&r.refCount, 1)
+       r.refCount.Add(1)
 }
 
 // Release decreases the reference count by 1.
 // When the reference count goes to zero, the memory is freed.
 // Release may be called simultaneously from multiple goroutines.
 func (r *Reader) Release() {
-       debug.Assert(atomic.LoadInt64(&r.refCount) > 0, "too many releases")
+       debug.Assert(r.refCount.Load() > 0, "too many releases")
 
-       if atomic.AddInt64(&r.refCount, -1) == 0 {
+       if r.refCount.Add(-1) == 0 {
                if r.rec != nil {
                        r.rec.Release()
                        r.rec = nil
@@ -280,6 +281,4 @@ func (r *Reader) Read() (arrow.Record, error) {
        return r.rec, nil
 }
 
-var (
-       _ array.RecordReader = (*Reader)(nil)
-)
+var _ array.RecordReader = (*Reader)(nil)
diff --git a/parquet/internal/bmi/bmi.go b/parquet/internal/bmi/bmi.go
index a12af3e..7139d6f 100644
--- a/parquet/internal/bmi/bmi.go
+++ b/parquet/internal/bmi/bmi.go
@@ -19,14 +19,20 @@
 // BMI2.
 package bmi
 
-import "math/bits"
+import (
+       "math/bits"
+)
 
 type funcs struct {
        extractBits func(uint64, uint64) uint64
        gtbitmap    func([]int16, int16) uint64
 }
 
-var funclist funcs
+// fallback until arch specific init() is called:
+var funclist = funcs{
+       extractBits: extractBitsGo,
+       gtbitmap:    greaterThanBitmapGo,
+}
 
 // ExtractBits performs a Parallel Bit extract as per the PEXT instruction for
 // x86/x86-64 cpus to use the second parameter as a mask to extract the bits 
from

Reply via email to