[gst-devel] Pthreads and cothreads

Erik Walthinsen omega at temple-baptist.com
Sun May 20 08:13:34 CEST 2001

I'm the lead developer of a project called GStreamer, which is a
multi-media framework.  It's currently looking as if it'll be the standard
media framework for GNOME 2.0, and a lot of other projects are porting to
it (DV/MJPEG stuff [I co-authored libdv...], 3ivx codec, etc.).

GStreamer makes use of a dual threading model, where pthreads are
explicitly defined based on the layout of the processing pipeline, and
cothreads are used to separate each component.  For instance:

|----------------------------|           |---------------|
| decodethread               |           | outputthread  |
| |---------|  |-----------| | |-------| | |-----------| |
| | disksrc |--| mp3decode |-|-| queue |-|-| audiosink | |
| |---------|  |-----------| | |-------| | |-----------| |
|----------------------------|           |---------------|

In the above pipeline (an mp3 player), there are two explicit threads
(decode and output), and a total of 4 elements.  For the sake of this
example, let's say that (except for the queue, which is special for
obvious reasons), each of the elements exists as its own main()-style
function.  That is, each has a while(1) loop, which as appropriate pulls
data from the left, processes, and pushes data to the right.

Now, this means that in the decodethread, disksrc and mp3decode have to
have their own context.  GStreamer uses a custom (small) cothread package
to provide this, which is your standard very small cothread_create,
cothread_switch.  pull() and push() simply utilize a shared holding pen
for a data pointer, and cothread_switch to the peer element.

There have been some concerns raised over the portability of this, and I
agree fully with them.  There are asm bits for x86, alpha, ppc, arm, and
sparc, and the DjVu coder has code for several other archs, but that
ignores the fact that there are other differences.

A key ingredient of the cothread routines that we use is the ability to
cooperate with pthreads.  This is accomplished by simply allocating the
cothread stack space within the pthread's stack.  This also has many
potential portability problems outside of the LinuxThreads world.  I
believe that it fails utterly on FreeBSD's user-space threads.

Now, it seems to me that IBM's M:N threads are adding this pthread-safety
to the GNU Pth package, though I see from the release notes that there are
still a number of issues remaining.  This could form the basis for a
cleaner solution for GStreamer.

The concern I have is over the definition of M:N (which I need clarified
more than anything).  What I understand is that M:N threading allows the
threading code to place various pthreads in different user-space threads
on various kernel threads.  This does not indicate that the application
has any control over where each thread goes.

A fundamental assumption in the GStreamer core is that switches between
elements within the same pthread are explicit.  That means there is no
locking overhead, just a spin-switch whenever the required data isn't
there yet.  This makes for extremely low-overhead pipelines (not as low as
stack-based, which is another option, but which is disabled right now for
simplicity), and greatly simplifies the execution model both from the
element and core points of view.

Is there any way to retain this capability with a system such as your M:N
pthreads?  Can the application request that a given set of threads exist
as user threads in a given kernel thread, such as to guarantee the
explicit switch semantics?  If not, is this somehow attainable?


      Erik Walthinsen <omega at temple-baptist.com> - System Administrator
       /  \                GStreamer - The only way to stream!
      |    | M E G A        ***** http://gstreamer.net/ *****
      _\  /_

More information about the gstreamer-devel mailing list