func (pm *PerfMap) Stop() {
	pm.stop <- true
}
Stop to poll the perf map readers after a maximum of 500ms
(the timeout we use for perf_reader_poll). Ideally we would
have a way to cancel the poll, but perf_reader_poll doesn't
support that yet.
package bcc
import (
	"encoding/binary"
	"fmt"
	"sync"
	"unsafe"
	"github.com/iovisor/gobpf/pkg/cpuonline"
)
import "C"
type PerfMap struct {
	table   *Table
	readers []*C.struct_perf_reader
	stop    chan bool
}
type callbackData struct {
	receiverChan chan []byte
}
const BPF_PERF_READER_PAGE_CNT = 8
var byteOrder binary.ByteOrder
var callbackRegister = make(map[uint64]*callbackData)
var callbackIndex uint64
var mu sync.Mutex
func init() {
	byteOrder = determineHostByteOrder()
}
func registerCallback(data *callbackData) uint64 {
	mu.Lock()
	defer mu.Unlock()
	callbackIndex++
	for callbackRegister[callbackIndex] != nil {
		callbackIndex++
	}
	callbackRegister[callbackIndex] = data
	return callbackIndex
}
func unregisterCallback(i uint64) {
	mu.Lock()
	defer mu.Unlock()
	delete(callbackRegister, i)
}
func lookupCallback(i uint64) *callbackData {
	return callbackRegister[i]
}
func callback_to_go(cbCookie unsafe.Pointer, raw unsafe.Pointer, rawSize C.int) {
	callbackData := lookupCallback(uint64(uintptr(cbCookie)))
	callbackData.receiverChan <- C.GoBytes(raw, rawSize)
}
func GetHostByteOrder() binary.ByteOrder {
	return byteOrder
}
func determineHostByteOrder() binary.ByteOrder {
	var i int32 = 0x01020304
	u := unsafe.Pointer(&i)
	pb := (*byte)(u)
	b := *pb
	if b == 0x04 {
		return binary.LittleEndian
	}
	return binary.BigEndian
}
func InitPerfMap(table *Table, receiverChan chan []byte) (*PerfMap, error) {
	fd := table.Config()["fd"].(int)
	keySize := table.Config()["key_size"].(uint64)
	leafSize := table.Config()["leaf_size"].(uint64)
	if keySize != 4 || leafSize != 4 {
		return nil, fmt.Errorf("passed table has wrong size")
	}
	callbackDataIndex := registerCallback(&callbackData{
		receiverChan,
	})
	key := make([]byte, keySize)
	leaf := make([]byte, leafSize)
	keyP := unsafe.Pointer(&key[0])
	leafP := unsafe.Pointer(&leaf[0])
	readers := []*C.struct_perf_reader{}
	cpus, err := cpuonline.Get()
	if err != nil {
		return nil, fmt.Errorf("failed to determine online cpus: %v", err)
	}
	for _, cpu := range cpus {
		reader, err := bpfOpenPerfBuffer(cpu, callbackDataIndex)
		if err != nil {
			return nil, fmt.Errorf("failed to open perf buffer: %v", err)
		}
		perfFd := C.perf_reader_fd((*C.struct_perf_reader)(reader))
		readers = append(readers, (*C.struct_perf_reader)(reader))
		byteOrder.PutUint32(leaf, uint32(perfFd))
		r, err := C.bpf_update_elem(C.int(fd), keyP, leafP, 0)
		if r != 0 {
			return nil, fmt.Errorf("unable to initialize perf map: %v", err)
		}
		r = C.bpf_get_next_key(C.int(fd), keyP, keyP)
		if r != 0 {
			break
		}
	}
	return &PerfMap{
		table,
		readers,
		make(chan bool),
	}, nil
}
func (pm *PerfMap) Start() {
	go pm.poll(500)
}