Fewer user-data parameters

Four `uX` parameters is overkill for a task.  We only need one.  I had
originally chosen four (or really, more than one) for the `flt_channel`
interface: I thought it would be nifty to have some of the parameters
provided by the channel constructor, and some by the sender.  But we can
mimic the same thing by sending a separate type into the channel
receiver, containing as many different fields as we need.  We now have a
bit of confusion over there being two separate things named `ud` in the
channel interface; it's probably worth renaming one of them.  But to
what...?
Bulk tasks

Each task now takes in an additional `size_t` input parameter.  This
lets you schedule “bulk” tasks, where the same task function is run
multiple times.  Each invocation gets the same `ud` parameter, and a
different `i` parameter.  When scheduling the bulk task, you get to
provide the minimum and maximum values to pass in for this new
parameter.

This lets you schedule huge numbers of embarrassingly parallel tasks in
a single call, which saves memory overhead and memory allocation time.
(The scheduler can blit through all of the bulk invocations more
quickly, too, since it's just advancing a counter and not popping new
elements off of a task queue.)
Tasks allocated by user code

(Most of) the `flt_run` functions now take in `flt_task` instances,
instead of the task function pointer and parameters; this means you must
now allocate `flt_task` instances directly.  This should simplify the
API a bit, since there won't be quite as many combinations of run
functions to define.

Note that the actual task constructor functions are defined as callbacks
inside of the `flt` execution context object.  This lets us squeeze out
a bit of performance by updating this callback function pointer, instead
of having to place lots of if statements inside of a single all-purpose
globally visible task constructor.
Task queues use doubly-linked lists

The task queues are all now implemented using doubly-linked lists,
instead of the previous singly-linked lists.  We'll need this when we
implement the work-stealing part of the scheduler, since it will need to
grab stuff from the back end of the queue.
Task groups

Each task now belongs to a group.  The only thing you can do with task
groups right now is detect when they finish executing.  You do this by
registering one or more “after” tasks, which the group will schedule to
be executed when all of the tasks in the group have finished executing.
Merge branch 'feature/bulk' into develop

* feature/bulk:
  Task groups
  Task queues use doubly-linked lists
  Tasks allocated by user code
  Bulk tasks
  Fewer user-data parameters