Neutrino offers a rich set of scheduling options with threads, the primary scheduling elements. Processes are defined as a unit of resource ownership (e.g., a memory area) and contain one or more threads.
Threads can use any of the following synchronization methods:
- mutexes—allow only one thread to own the mutex at a given point in time.
- semaphores—allow a fixed number of threads to own the semaphore.
- sleepons—allow a number of threads to block on a number of objects, while allocating the underlying condvars dynamically to the blocked threads.
- condvars—similar to sleepons except that the allocation of the condvars is controlled by the programmer.
- joining—allows a thread to synchronize to the termination of another thread.
- barriers—allows threads to wait until a number of threads have reached the synchronization point.
Note that mutexes, semaphores, and condition variables can be used between threads in the same or different processes, but that sleepons can be used only between threads in the same process (because the library has a mutex hidden in the process's address space).
As well as synchronization, threads can be scheduled (using a priority and a scheduling algorithm), and they'll automatically run on a single-processor box or an SMP box.
Whenever we talk about creating a process (mainly as a means of porting code from single-threaded implementations), we're really creating an address space with one thread running in it—that thread starts at main() or at fork() or vfork() depending on the function called.