Add mutex and semaphore documentation

Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/commit/0d1d4fc9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/0d1d4fc9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/0d1d4fc9

Branch: refs/heads/asf-site
Commit: 0d1d4fc9aff099295aa3f001e190966c0ee6b823
Parents: 53f5361
Author: wes3 <w...@micosa.io>
Authored: Wed Jan 6 10:42:03 2016 -0800
Committer: wes3 <w...@micosa.io>
Committed: Wed Jan 6 10:42:03 2016 -0800

----------------------------------------------------------------------
 docs/os/mutex.md     | 158 ++++++++++++++++++++++++++++++++++------------
 docs/os/semaphore.md | 158 ++++++++++++++++++++++++++++++++++------------
 2 files changed, 235 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/0d1d4fc9/docs/os/mutex.md
----------------------------------------------------------------------
diff --git a/docs/os/mutex.md b/docs/os/mutex.md
index 0e0c329..d11fcf8 100644
--- a/docs/os/mutex.md
+++ b/docs/os/mutex.md
@@ -6,11 +6,34 @@ Mutex is short for "mutual exclusion"; a mutex provides 
mutually exclusive acces
 
 ## Description
 
-Describe OS feature here 
+The first order of business when using a mutex is to declare the mutex 
globally. The mutex needs to be initialized before it is used (see the 
examples). It is generally a good idea to initialize the mutex before tasks 
start running in order to avoid a task possibly using the mutex before it is 
initialized.
+
+When a task wants exclusive access to a shared resource it needs to obtain the 
mutex by calling *os_mutex_pend*. If the mutex is currently owned by a 
different task (a lower priority task), the requesting task will be put to 
sleep and the owners priority will be elevated to the priority of the 
requesting task. Note that multiple tasks can request ownership and the current 
owner is elevated to the highest priority of any task waitin on the mutex. When 
the task is done using the shared resource, it needs to release the mutex by 
called *os_mutex_release*. There needs to be one release per call to pend. Note 
that nested calls to *os_mutex_pend* are allowed but there needs to be one 
release per pend.
+
+The following example will illustrate how priority inheritance works. In this 
example, the task number is the same as its priority. Remember that the lower 
the number, the higher the priority (i.e. priority 0 is higher priority than 
priority 1). Suppose that task 5 gets ownership of a mutex but is preempted by 
task 4. Task 4 attempts to gain ownership of the mutex but cannot as it is 
owned by task 5. Task 4 is put to sleep and task 5 is temporarily raised to 
priority 4. Before task 5 can release the mutex, task 3 runs and attempts to 
acquire the mutex. At this point, both task 3 and task 4 are waiting on the 
mutex (sleeping). Task 5 now runs at priority 3 (the highest priority of all 
the tasks waiting on the mutex). When task 5 finally releases the mutex it will 
be preempted as two higher priority tasks are waiting for it. 
+
+Note that when multiple tasks are waiting on a mutex owned by another task, 
once the mutex is released the highest priority task waiting on the mutex is 
run. 
 
 ## Data structures
 
-Replace this with the list of data structures used, why, any neat features
+```
+struct os_mutex
+{
+    SLIST_HEAD(, os_task) mu_head;
+    uint8_t     _pad;
+    uint8_t     mu_prio;
+    uint16_t    mu_level;
+    struct os_task *mu_owner;
+};
+
+```
+| Element | Description |
+|-----------|-------------|
+| mu_head |  Queue head for list of tasks waiting on mutex  |
+| _pad |  Padding  |
+| mu_prio |  Default priority of owner of mutex. Used to reset priority of 
task when mutex released  |
+| mu_level | Call nesting level (for nested calls) |
+| mu_owner | Pointer to task structure which owns mutex |
 
 ## List of Functions
 
@@ -20,8 +43,8 @@ The functions available in this OS feature are:
 
 * [os_mutex_init](#function-os_mutex_init)
 * [os_mutex_release](#function-os_mutex_release)
-* add the rest
-
+* [os_mutex_pend](#function-os_mutex_pend)
+* [os_mutex_delete](#function-os_mutex_delete)
 
 ## Function Reference
 
@@ -30,39 +53,39 @@ The functions available in this OS feature are:
 ### <font color="2980b9">function os_mutex_init</font>
 
 ```
-    os_error_t
-    os_mutex_init(struct os_mutex *mu)
+os_error_t os_mutex_init(struct os_mutex *mu)
     
 ```
 
-<Insert short description>
-
+Initialize the mutex. Must be called before the mutex can be used.
 
 #### Arguments
 
 | Arguments | Description |
 |-----------|-------------|
-| xx |  explain argument xx  |
-| yy |  explain argument yy  |
+| *mu|  Pointer to mutex  |
 
 #### Returned values
 
-List any values returned.
-Error codes?
+OS_INVALID_PARM: returned when *mu is NULL on entry.
+
+OS_OK: mutex initialized successfully.
 
 #### Notes 
 
-Any special feature/special benefit that we want to tout. 
+<Any special feature/special benefit that we want to tout. 
 Does it need to be used with some other specific functions?
-Any caveats to be careful about (e.g. high memory requirements).
+Any caveats to be careful about (e.g. high memory requirements).>
 
 #### Example
 
-<Add text to set up the context for the example here>
 
 ```
+struct os_mutex g_mutex1;
+os_error_t err;
 
-<Insert the code snippet here>
+err = os_mutex_init(&g_mutex1);
+assert(err == OS_OK);
 
 ```
 
@@ -71,80 +94,135 @@ Any caveats to be careful about (e.g. high memory 
requirements).
 ### <font color="#2980b9"> function os_mutex_release</font>
 
 ```
-   <Insert function callout here >
+os_error_t os_mutex_release(struct os_mutex *mu)
+
    
 ```
 
-<Insert short description>
+Release ownership of a mutex
 
 
 #### Arguments
 
 | Arguments | Description |
 |-----------|-------------|
-| xx |  explain argument xx  |
-| yy |  explain argument yy  |
+| *mu|  Pointer to mutex  |
 
 #### Returned values
+OS_INVALID_PARM: returned when *mu is NULL on entry.
 
-List any values returned.
-Error codes?
+OS_OK: mutex initialized successfully.
 
-#### Notes 
+OS_BAD_MUTEX: The mutex was not owned by the task attempting to release it.
+
+OS_NOT_STARTED: Attempt to release a mutex before the os has been started.
 
-Any special feature/special benefit that we want to tout. 
-Does it need to be used with some other specific functions?
-Any caveats to be careful about (e.g. high memory requirements).
 
 #### Example
 
-<Add text to set up the context for the example here>
 
 ```
+struct os_mutex g_mutex1;
+os_error_t err;
+
+err = os_mutex_pend(&g_mutex1, 0);
+assert(err == OS_OK);
+
+/* Perform operations requiring exclusive access */
 
-<Insert the code snippet here>
+err = os_mutex_release(&g_mutex1);
+assert(err == OS_OK);
 
 ```
 
 ---------------------
    
-### <font color="#2980b9"> function next_one </font>
+### <font color="#2980b9"> function os_mutex_pend </font>
 
 ```
-   <Insert function callout here >
+os_error_t os_mutex_pend(struct os_mutex *mu, uint32_t timeout)
    
 ```
 
-<Insert short description>
+Acquire ownership of a mutex.
 
 
 #### Arguments
 
 | Arguments | Description |
 |-----------|-------------|
-| xx |  explain argument xx  |
-| yy |  explain argument yy  |
+| *mu |  Pointer to mutex  |
+| timeout | Timeout, in os ticks. A value of 0 means no timeout. A value of 
0xFFFFFFFF means to wait forever.   |
 
 #### Returned values
 
-List any values returned.
-Error codes?
+OS_INVALID_PARM: returned when *mu is NULL on entry.
+
+OS_OK: mutex was successfully acquired.
+
+OS_TIMEOUT: the mutex was not available within the timeout specified.
+
+OS_NOT_STARTED: Attempt to release a mutex before the os has been started.
+
 
 #### Notes 
 
-Any special feature/special benefit that we want to tout. 
-Does it need to be used with some other specific functions?
-Any caveats to be careful about (e.g. high memory requirements).
+If the mutex is owned by another task and the timeout is 0 the function 
returns immediately with the error code OS_TIMEOUT. The calling task *does not* 
own the mutex when this occurs.
 
 #### Example
 
-<Add text to set up the context for the example here>
+
 
 ```
+struct os_mutex g_mutex1;
+os_error_t err;
+
+err = os_mutex_pend(&g_mutex1, 0);
+assert(err == OS_OK);
+
+/* Perform operations requiring exclusive access */
+
+err = os_mutex_release(&g_mutex1);
+assert(err == OS_OK);
 
-<Insert the code snippet here>
 
 ```
 
 ---------------------
 
+### <font color="#2980b9"> function os_mutex_delete </font>
+
+```
+os_error_t os_mutex_pend(struct os_mutex *mu)
+   
+```
+
+Delete a mutex
+
+#### Arguments
+
+| Arguments | Description |
+|-----------|-------------|
+| *mu |  Pointer to mutex  |
+
+#### Returned values
+
+OS_INVALID_PARM: returned when *mu is NULL on entry.
+
+OS_OK: mutex initialized successfully.
+
+OS_NOT_STARTED: Attempt to release a mutex before the os has been started.
+
+#### Example
+
+```
+struct os_mutex g_mutex1;
+os_error_t err;
+
+err = os_mutex_delete(&g_mutex1);
+assert(err == OS_OK);
+
+
+```
+
+---------------------

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/0d1d4fc9/docs/os/semaphore.md
----------------------------------------------------------------------
diff --git a/docs/os/semaphore.md b/docs/os/semaphore.md
index c05a1a8..fe69644 100644
--- a/docs/os/semaphore.md
+++ b/docs/os/semaphore.md
@@ -1,16 +1,34 @@
 # Semaphore
 
-
-Insert synopsis here
+A semaphore is a structure used for gaining exclusive access (much like a 
mutex), synchronizing task operations and/or use in a "producer/consumer" 
roles. Semaphores like the ones used by the myNewt OS are called "counting" 
semaphores as they are allowed to have more than one token (explained below).
 
 
 ## Description
 
-Describe OS feature here 
+A semaphore is a fairly simple construct consisting of a queue for waiting 
tasks and the number of tokens currently owned by the semaphore. A semaphore 
can be obtained as long as there are tokens in the semaphore. Any task can add 
tokens to the semaphore and any task can request the semaphore, thereby 
removing tokens. When creating the semaphore, the initial number of tokens can 
be set as well.
+
+When used for exclusive access to a shared resource the semaphore only needs a 
single token. In this case, a single task "creates" the semaphore by calling 
*os_sem_init* with a value of one (1) for the token. When a task desires 
exclusive access to the shared resource it requests the semaphore by calling 
*os_sem_pend*. If there is a token the requesting task will acquire the 
semaphore and continue operation. If no tokens are available the task will be 
put to sleep until there is a token. A common "problem" with using a semaphore 
for exclusive access is called *priority inversion*. Consider the following 
scenario: a high and low priority task both share a resource which is locked 
using a semaphore. If the low priority task obtains the semaphore and then the 
high priority task requests the semaphore, the high priority task is now 
blocked until the low priority task releases the semaphore. Now suppose that 
there are tasks between the low priority task and the high priority task that wa
 nt to run. These tasks will preempt the low priority task which owns the 
semaphore. Thus, the high priority task is blocked waiting for the low priority 
task to finish using the semaphore but the low priority task cannot run since 
other tasks are running. Thus, the high priority tasks is "inverted" in 
priority; in effect running at a much lower priority as normally it would 
preempt the other (lower priority) tasks. If this is an issue a mutex should be 
used instead of a semaphore.
+
+Semaphores can also be used for task synchronization. A simple example of this 
would be the following. A task creates a semaphore and initializes it with no 
tokens. The task then waits on the semaphore, and since there are no tokens, 
the task is put to sleep. When other tasks want to wake up the sleeping task 
they simply add a token by calling *os_sem_release*. This will cause the 
sleeping task to wake up (instantly if no other higher priority tasks want to 
run).
+
+The other common use of a counting semaphore is in what is commonly called a 
"producer/consumer" relationship. The producer adds tokens (by calling 
*os_sem_release*) and the consumer consumes them by calling *os_sem_pend*. In 
this relationship, the producer has work for the consumer to do. Each token 
added to the semaphore will cause the consumer to do whatever work is required. 
A simple example could be the following: every time a button is pressed there 
is some work to do (ring a bell). Each button press causes the producer to add 
a token. Each token consumed rings the bell. There will exactly the same number 
of bell rings as there are button presses. In other words, each call to 
*os_sem_pend* subtracts exactly one token and each call to *os_sem_release* 
adds exactly one token.
 
 ## Data structures
+```
 
-Replace this with the list of data structures used, why, any neat features
+struct os_sem
+{
+    SLIST_HEAD(, os_task) sem_head;     /* chain of waiting tasks */
+    uint16_t    _pad;
+    uint16_t    sem_tokens;             /* # of tokens */
+};
+```
+
+| Element | Description |
+|-----------|-------------|
+| sem_head |  Queue head for list of tasks waiting on semaphore |
+| _pad |  Padding for alignment  |
+| sem_tokens | Current number of tokens |
 
 ## List of Functions
 
@@ -20,7 +38,8 @@ The functions available in this OS feature are:
 
 * [os_sem_init](#function-os_sem_init)
 * [os_sem_release](#function-os_sem_release)
-* add the rest
+* [os_sem_pend](#function-os_sem_pend)
+* [os_sem_delete](#function-os_sem_delete)
 
 
 ## Function Reference
@@ -30,39 +49,42 @@ The functions available in this OS feature are:
 ### <font color="2980b9">function os_sem_init</font>
 
 ```
-    os_error_t
-    os_sem_init(struct os_sem *sem, uint16_t tokens)    
+    os_error_t os_sem_init(struct os_sem *sem, uint16_t tokens)    
 
 ```
 
-<Insert short description>
+Initialize a semaphore with a given number of tokens. Should be called before 
the semaphore is used.
 
 
 #### Arguments
 
 | Arguments | Description |
 |-----------|-------------|
-| xx |  explain argument xx  |
-| yy |  explain argument yy  |
+| *sem |  Pointer to semaphore  |
+| tokens |  Initial number of tokens allocated to semaphore  |
 
 #### Returned values
 
-List any values returned.
-Error codes?
+OS_INVALID_PARM: returned when *sem is NULL on entry.
+
+OS_OK: semaphore initialized successfully.
 
 #### Notes 
 
-Any special feature/special benefit that we want to tout. 
+<Any special feature/special benefit that we want to tout. 
 Does it need to be used with some other specific functions?
-Any caveats to be careful about (e.g. high memory requirements).
+Any caveats to be careful about (e.g. high memory requirements).>
 
 #### Example
 
-<Add text to set up the context for the example here>
+The following example shows how to initialize a semaphore used for exclusive 
access.
 
 ```
+struct os_mutex g_os_sem;
+os_error_t err;
 
-<Insert the code snippet here>
+err = os_sem_init(&g_os_sem, 1);
+assert(err == OS_OK);
 
 ```
 
@@ -71,78 +93,132 @@ Any caveats to be careful about (e.g. high memory 
requirements).
 ### <font color="#2980b9"> function os_sem_release </font>
 
 ```
-   <Insert function callout here >
+os_error_t os_sem_release(struct os_sem *sem)
    
 ```
 
-<Insert short description>
+Release a semaphore that you are holding. This adds a token to the semaphore.
 
 
 #### Arguments
 
 | Arguments | Description |
 |-----------|-------------|
-| xx |  explain argument xx  |
-| yy |  explain argument yy  |
+| *sem |  Pointer to semaphore  |
 
 #### Returned values
 
-List any values returned.
-Error codes?
+OS_NOT_STARTED: Called before os has been started.
+
+OS_INVALID_PARM: returned when *sem is NULL on entry.
+
+OS_OK: semaphore released successfully.
 
 #### Notes 
 
-Any special feature/special benefit that we want to tout. 
-Does it need to be used with some other specific functions?
-Any caveats to be careful about (e.g. high memory requirements).
 
 #### Example
 
-<Add text to set up the context for the example here>
-
 ```
+struct os_sem g_os_sem;
+os_error_t err;
 
-<Insert the code snippet here>
+err = os_sem_pend(&g_os_sem, OS_TIMEOUT_NEVER);
+assert(err == OS_OK);
+
+/* Perform operations requiring semaphore lock */
+
+err = os_sem_release(&g_os_sem);
+assert(err == OS_OK);
 
 ```
 
 ---------------------
    
-### <font color="#2980b9"> function next_one </font>
+### <font color="#2980b9"> function os_sem_pend </font>
 
 ```
-   <Insert function callout here >
+os_error_t os_sem_pend(struct os_sem *sem, uint32_t timeout)
    
 ```
 
-<Insert short description>
-
+Wait for a semaphore for a given amount of time.
 
 #### Arguments
 
 | Arguments | Description |
 |-----------|-------------|
-| xx |  explain argument xx  |
-| yy |  explain argument yy  |
+| *sem |  Pointer to semaphore  |
+| timeout |  Amount of time, in os ticks, to wait for semaphore. A value of 0 
means no wait. A value of 0xFFFFFFFF means wait forever.  |
 
 #### Returned values
 
-List any values returned.
-Error codes?
+OS_INVALID_PARM: returned when *sem is NULL on entry.
+
+OS_OK: semaphore acquired successfully.
+
+OS_TIMEOUT: the semaphore was not available within the timeout specified.
+
+OS_NOT_STARTED: Attempt to release a semaphore before os started.
 
 #### Notes 
 
-Any special feature/special benefit that we want to tout. 
-Does it need to be used with some other specific functions?
-Any caveats to be careful about (e.g. high memory requirements).
+If a timeout of 0 is used and the function returns OS_TIMEOUT, the semaphore 
was not available and was not acquired. No release of the semaphore should 
occur and the calling task does not own the semaphore.
 
 #### Example
 
-<Add text to set up the context for the example here>
+```
+struct os_sem g_os_sem;
+os_error_t err;
+
+err = os_sem_pend(&g_os_sem, OS_TIMEOUT_NEVER);
+assert(err == OS_OK);
+
+/* Perform operations requiring semaphore lock */
+
+err = os_sem_release(&g_os_sem);
+assert(err == OS_OK);
+
+```
+
+---------------------
+
+### <font color="#2980b9"> function os_sem_delete </font>
 
 ```
+os_error_t os_sem_delete(struct os_sem *sem)
+   
+```
+
+Delete a semaphore
+
+#### Arguments
+
+| Arguments | Description |
+|-----------|-------------|
+| *sem |  Pointer to semaphore  |
+
+#### Returned values
+
+OS_INVALID_PARM: returned when *sem is NULL on entry.
+
+OS_OK: semaphore deleted successfully.
+
+OS_NOT_STARTED: Attempt to release a semaphore before os started.
+
+#### Notes 
+
+Care must be taken when deleting a semaphore as deleting a semaphore used by 
other tasks could causes unexpected/unwanted behavior.
+
+#### Example
+
+```
+struct os_sem g_os_sem;
+os_error_t err;
+
+err = os_sem_delete(&g_os_sem);
+assert(err == OS_OK);
 
-<Insert the code snippet here>
 
 ```
 

Reply via email to