Example #1
0
//export goGenericAlloc
func goGenericAlloc(t unsafe.Pointer, n C.Py_ssize_t) unsafe.Pointer {
	var obj *C.PyObject

	typ := newType((*C.PyObject)(t))
	size := uintptr(C.var_size(c(typ), n))

	if typ.IsGc() {
		obj = goGcMalloc(size)
	} else {
		obj = goMalloc(size)
	}

	if obj == nil {
		raise(MemoryError.ErrV(None))
		return nil
	}

	if typ.o.tp_flags&C.Py_TPFLAGS_HEAPTYPE != 0 {
		typ.Incref()
	}

	if typ.o.tp_itemsize == 0 {
		C.GoPyObject_INIT(obj, c(typ))
	} else {
		C.GoPyObject_INIT_VAR(obj, c(typ), n)
	}

	if typ.IsGc() {
		C.GoPyObject_GC_Track(obj)
	}

	return unsafe.Pointer(obj)
}
Example #2
0
func goGcMalloc(size uintptr) *C.PyObject {
	// first, lock memLock, and arrange for it to be unlocked on return
	memLock.Lock()
	defer memLock.Unlock()

	g := (*C.PyGC_Head)(unsafe.Pointer(_goMalloc(size + headSize)))
	C.setGcRefs(g, C._PyGC_REFS_UNTRACKED)
	p := fromGc(g)

	// We need to move the original tracked entry to be indexed by the offset
	// address from fromGc
	px := uintptr(unsafe.Pointer(p))
	gx := uintptr(unsafe.Pointer(g))
	allocated[px] = allocated[gx]
	delete(allocated, gx)

	// We can't access the internals of the GC Module to manipulate the
	// generation counts, so we have to use a proxy object instead.  We just
	// create a bare minimum object, initialise it, and then store it away to be
	// cleaned up later.
	proxy := C._PyObject_GC_Malloc(C.size_t(baseSize))
	if proxy == nil {
		delete(allocated, px)
		return nil
	}
	C.GoPyObject_INIT(proxy, c(BaseType))
	gcProxies[px] = proxy

	return p
}