Skip to menu


libmill 是一个 Go 语言风格的 C 并发编程库。每秒可实现 2000 - 5000 万的协程上下文切换。



Libmill is a lightweight coroutine library bringing Go-style concurrency to C language. It also contains simple networking and file access library that allows users to quickly bootstrap application development.

Libmill runs in following environments:

  • Microarchitecture: x86_64, ARM
  • Compiler: gcc, clang
  • Operating system: Linux, OSX, FreeBSD, OpenBSD, NetBSD, DragonFlyBSD

Whether it works in different environments is not known - please, do report any successes or failures to the project mailing list.

Download the package from the download page. Then build and install as follows:

$ tar -xzf libmill-1.16.tar.gz
$ cd libmill-1.16
$ ./configure
$ make
$ make check
$ sudo make install

After the installation there's libmill.h header file available as well as dynamic library and static library libmill.a.

A program using the library can look, for example, like this:

#include <stdio.h>
#include <libmill.h>

coroutine void worker(int count, const char *text) {
    int i;
    for(i = 0; i != count; ++i) {
        printf("%s\n", text);
        msleep(now() + 10);

int main() {
    go(worker(4, "a"));
    go(worker(2, "b"));
    go(worker(3, "c"));
    msleep(now() + 100);
    return 0;

To build and run the example:

$ gcc -o example example.c -lmill
$ ./example

Alternatively, using static library:

$ gcc -o example example.c libmill.a
$ ./example

Libmill defines some fairly generic symbols like in or go. If it clashes with other libraries you can defineMILL_USE_PREFIX macro before including the header file. That will add mill_ (or MILL_) prefix to all the defined symbols. For example:

#include <libmill.h>

mill_coroutine void worker(void) {

int main() {
    return 0;

A tour of the library


Coroutine is defined using coroutine keyword and launched using go construct:

coroutine void foo(int i, int j) {

int main() {
    go(foo(1, 2));
    return 0;

Although coroutine can return a value keep in mind that it is executed asynchronously and thus there is now way to retrieve the result.

Note that your program may work perfectly well even if you ommit the coroutine keyword. However, such program may break randomly when compiled by a different compiler or with a different optimisation level (a known problem is with clang and -O2 optimisation level).

Also bear in mind that coroutines are scheduled in a cooperative fashion. If one coroutine blocks, for example by calling sleep(), it blocks the entire process. Therefore, coroutine-friendly versions of blocking functions (such as msleep() or fdwait(), see below) should be used.

In case of need, you can yield CPU to other coroutines explicitly: