Cgo and threads

2,807 views
Skip to first unread message

Olivier Gagnon

unread,
Aug 10, 2011, 2:31:08 PM8/10/11
to golan...@googlegroups.com
I am working with a C librairy which is not completely thread-safe. I would like
to understand when does cgo creates and uses threads. Does cgo create a new thread
each time it enters C code. If I use GOMAXPROCS = 1, will only one thread be 
executed at the time?

Thank you,
Olivier Gagnon

Brad Fitzpatrick

unread,
Aug 10, 2011, 3:00:29 PM8/10/11
to golan...@googlegroups.com
Btw, do you know about http://golang.org/pkg/runtime/#LockOSThread ?

Brad Fitzpatrick

unread,
Aug 10, 2011, 3:05:27 PM8/10/11
to golan...@googlegroups.com
Oh, sorry, skimmed your message too quickly.  I assumed too quickly this was a question about thread-locals in a C library.

Iiuc, cgo doesn't create a new thread whenever it enters C code (that'd be pretty expensive), but it does assume that it's going to block on something, so marks the calling goroutine as probably lost for awhile, and if something other goroutine is otherwise runnable, it can create a new thread to run that other goroutine while your C one blocks.

Depending on how delicate your C code is, you may want to only call into it from one goroutine (using LockOSThread), and have other goroutines interact with it by communicating over channels with the C-owning goroutine.  But it all depends what restrictions your C library puts you under.

Gustavo Niemeyer

unread,
Aug 10, 2011, 3:30:12 PM8/10/11
to golan...@googlegroups.com
Hey Olivier,

> I am working with a C librairy which is not completely thread-safe. I would

If the only constraint you have is that the C library is not
_thread-safe_, and as long as the C library doesn't have local
thread-storage, you don't really have to care about which OS-thread is
running it. You just must ensure it's not being called concurrently,
which is a much nicer constraint to work with than restricting logic
to a named thread.

One straightforward way to handle that is to have a global lock,
managed in the Go side of your API, that you acquire and release as
you touch the C library internals. This will avoid reserving an OS
thread, will enable multiple goroutines to interact with the Go
interface of your package, and will also be very fast if it's not
being used concurrently, since the locks are generally optimized away
with atomic operations if you have a single client.

If you have other constraints, then there are different approaches
that may be used.

--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog

-- I never filed a patent.

Russ Cox

unread,
Aug 10, 2011, 6:13:12 PM8/10/11
to golan...@googlegroups.com
The Go runtime creates threads as needed and can
move a goroutine from one thread to another at any time.
In particular, every call to C.foo, even within a single
goroutine, might happen on a different OS thread.

GOMAXPROCS limits the number of threads running
Go code, but cgo calls do not count as Go code, so
you can still see multiple threads with GOMAXPROCS=1.

If the library is squirreling away OS-thread-local data
then you need runtime.LockOSThread. If not, then
you just need a mutex.

Russ

Reply all
Reply to author
Forward
0 new messages