/*
    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
    This file is part of ChibiOS/RT.
    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
*/
/**
 * @page article_mutual_exclusion Mutual Exclusion guide
 * The most common problem when writing multithreaded code is the
 * synchronization on the shared resources/services.
 * ChibiOS/RT offers a rich variety of mechanisms that apparently solve the
 * same problem. I wrote apparently because each mechanism has its pro and
 * cons.
 * This article will introduce the various mechanisms and the explain the
 * right scenarios for each one.
 *
 * 
Basics
 * Some of the concepts mentioned in this article can be found in the
 * following Wikipedia articles:
 * - 
 *   Mutual Exclusion
 * - 
 *   Priority Inversion
 * - Priority Inheritance
 * - 
 *   Priority Ceiling
 * .
 * Mutual exclusion by System Locks
 * This is the lowest level mechanism, the system is locked by invoking the
 * @p chSysLock() API and then unlocked by invoking @p chSysUnlock().
 * The implementation is architecture dependent but it is guaranteed to, at
 * least, disable the interrupt sources with hardware priority below or equal
 * the kernel level.
 *
 * Advantages
 * - It is the lightest as execution time, often a lock or unlock becomes just a
 *   single inlined assembler instruction.
 * - It ensures mutual exclusion among threads but also interrupt handling code.
 * - The implementation would ensure mutual exclusion even on multicore
 *   architectures where multiple hardware threads are present.
 * .
 * Disadvantages
 * - Disabling interrupts for a long period of time can deteriorate the overall
 *   system response time and/or introduce jitter.
 * .
 * When use Locks
 * - When mutual exclusion with interrupt handlers is required.
 * - When the operation within the lock zone is very simple and has finite
 *   time.
 * .
 * Example
 * @code
 * ...
 * chSysLock();
 * /* Protected code */
 * chSysUnlock();
 * ...
 * @endcode
 *
 * Mutual exclusion by Semaphores
 * In ChibiOS/RT the counting semaphores are mainly meant as a
 * synchronization mechanism between interrupt handlers and high level code
 * running at thread level. Usually a thread waits on a semaphore that is
 * signaled asynchronously by an interrupt handler.
 * The semaphores can, however, be used as simple mutexes by initializing
 * counter to one.
 *
 * Advantages
 * - The semaphores code is "already there" if you use the I/O queues and
 *   you don't want to enable the mutexes too because space constraints.
 * - Semaphores are lighter than mutexes because their queues are FIFO
 *   ordered and do not have any overhead caused by the priority inheritance
 *   algorithm.
 * - A semaphore takes less RAM than a mutex (12 vs 16 bytes on 32 bit
 *   architectures).
 * .
 * Disadvantages
 * - Semaphore queues are FIFO ordered by default, an option exist to make
 *   them priority ordered but this can impact I/O performance because
 *   semaphores are used in I/O queues.
 * - Semaphores do not implement the Priority Inheritance algorithm.
 * .
 * When use Semaphores
 * - When you don't need queuing by priority nor the Priority Inheritance
 *   algorithm.
 * - When RAM/ROM space is scarce.
 * .
 * Example
 * @code
 * static Semaphore sem; /* Semaphore declaration */
 * ...
 * chSemInit(&sem, 1); /* Semaphore initialization before use */
 * ...
 * chSemWait(&sem);
 * /* Protected code */
 * chSemSignal(&sem);
 * ...
 * @endcode
 *
 * Mutual exclusion by Mutexes
 * The mutexes, also known as binary semaphores (we choose to not use this
 * terminology to avoid confusion with counting semaphores), are the mechanism
 * intended as general solution for Mutual Exclusion.
 *
 * Advantages
 * - Mutexes implement the Priority Inheritance algorithm that is an important
 *   tool in reducing jitter and improve overall system response time (it is
 *   not a magic solution, just a tool for the system designer).
 * .
 * Disadvantages
 * - Heaviest among all the possible choices. The Priority Inheritance method
 *   is efficiently implemented but nothing is more efficient than no code at
 *   all.
 * .
 * When use Mutexes
 * - When you are designing a very complex system with hard realtime
 *   requirements.
 * .
 * Example
 * @code
 * static Mutex mtx; /* Mutex declaration */
 * ...
 * chMtxInit(&mtx); /* Mutex initialization before use */
 * ...
 * chMtxLock(&mtx);
 * /* Protected code */
 * chMtxUnlock();
 * ...
 * @endcode
 *
 * Mutual exclusion by priority boost
 * Another way to implement mutual exclusion is to boost the thread priority
 * to a level higher than all of the threads competing for a certain resource.
 * This solution effectively implements an Immediate Priority Ceiling
 * algorithm.
 *
 * Advantages
 * - Almost free as code size, you need no semaphores nor mutexes.
 * - No RAM overhead.
 * - Fast execution, priority change is a quick operation under ChibiOS/RT.
 * - The Priority Ceiling protocol can help mitigate potential Priority
 *   Inversion problems.
 * .
 * Disadvantages
 * - Makes the design more complicated because priorities must be assigned to
 *   not just threads but also assigned to the resources to be protected.
 * - Locking a resource affects all the threads with lower priority even if
 *   not interested to the resource.
 * - All the threads that can access the resource must have lower priority
 *   than the resource itself.
 * - The mechanism is not easy to understand in the code unless it is clearly
 *   documented.
 * - This method does not work in on multicore architectures where multiple
 *   hardware threads are present.
 * - Only useful in very simple applications.
 * .
 * Example
 * @code
 * /* Priority assigned to the resource, threads must have lower
 *    priority than this.*/
 * #define AAA_RESOURCE_PRIORITY NORMALPRIO+10
 * ...
 * /* Locks the resources AAA.*/
 * tprio_t aaa_old_prio = chThdSetPriority(AAA_RESOURCE_PRIORITY);
 * /* Accessing resource AAA */
 * chThdSetPriority(aaa_old_prio); /* Unlocks AAA.*/
 * ...
 * @endcode
 *
 * Mutual exclusion by message passing
 * Another method is to make a single dedicated thread execute the critical
 * code and make it work as a messages server. The other threads can request
 * the service to the server by sending a properly formatted message and
 * then wait for the answer with the result.
 * This method is very useful when integrating into the system components not
 * designed to be reentrant or to be executed in a multithreaded environment,
 * as example a 3rd part file system or a networking protocol stack.
 *
 * Advantages
 * - It is possible to encapsulate very complex logic without worry about
 *   about concurrent accesses.
 * - If the encapsulate code uses a large stack area only the server thread
 *   have to allocate enough RAM, the client threads save RAM by just
 *   requesting the service to the server.
 * - Clean system architecture.
 * - This method also implements a form of Priority Ceiling. The ceiling is
 *   the priority of the server thread itself.
 * .
 * Disadvantages
 * - More complex implementation, a protocol must be created between clients
 *   and server.
 * - Two context switches are required for each request to the server (but
 *   ChibiOSRT is very efficient at that).
 * - Requires a dedicated thread as server.
 * .
 */