Nrk-api-signals-semaphores

Version 20 (Anthony Rowe, 06/08/2007 08:50 pm)

1 11 Anthony Rowe
= Signals =
2 1 Anthony Rowe
3 1 Anthony Rowe
A signal is a message that a task can use to wakeup one or more tasks waiting on an
4 1 Anthony Rowe
event or events. When waiting on an event, a task is suspended and does not consume
5 4 Anthony Rowe
CPU time. Nano-RK supports 32 unique signals. It is possible to wait on multiple
6 1 Anthony Rowe
signals such that any one of them can wake a task from sleep. All signals must be
7 6 Anthony Rowe
created using nrk_sig_create() before they can be used.  Any task that wishes to wakeup on a signal
8 6 Anthony Rowe
must register the signal using nrk_sig_register().  There are a few special case signals that are
9 6 Anthony Rowe
generated by the kernel used to support event timeouts and notification of special actions.  See the
10 15 Anthony Rowe
'''Special Kernel Signals''' subsection for more information.  For more information about signals, please refer
11 14 Anthony Rowe
to the basic_signals project that comes with Nano-RK: 
12 14 Anthony Rowe
http://www.nanork.org:8000/nano-RK/browser/nano-RK/projects/basic_signals/main.c
13 1 Anthony Rowe
14 11 Anthony Rowe
15 5 Anthony Rowe
{{{
16 5 Anthony Rowe
#!c
17 5 Anthony Rowe
// This is a macro used to convert a signal into a bitmask for nrk_event_wait()
18 5 Anthony Rowe
// See nrk_event_wait() for an example.
19 5 Anthony Rowe
#define SIG(x)  ((uint32_t)1)<<x 
20 5 Anthony Rowe
21 5 Anthony Rowe
// These are typedefs used to represent signals and semaphores
22 5 Anthony Rowe
typedef int8_t nrk_sig_t;
23 5 Anthony Rowe
typedef uint32_t nrk_sig_mask_t;
24 5 Anthony Rowe
typedef int8_t nrk_sem_t;
25 5 Anthony Rowe
}}}
26 5 Anthony Rowe
27 5 Anthony Rowe
28 4 Anthony Rowe
'''nrk_sig_mask_t nrk_get_active_signal_mask();'''
29 1 Anthony Rowe
30 4 Anthony Rowe
'''int8_t nrk_delete_signal(nrk_sig_t sig_id);'''
31 1 Anthony Rowe
32 4 Anthony Rowe
'''int8_t nrk_signal_unregister(nrk_sig_t sig_id);'''
33 1 Anthony Rowe
34 4 Anthony Rowe
'''int8_t nrk_signal_register(nrk_sig_t sig_id);'''
35 1 Anthony Rowe
36 4 Anthony Rowe
'''nrk_sig_t nrk_signal_create();'''
37 1 Anthony Rowe
38 4 Anthony Rowe
'''int8_t nrk_event_signal(nrk_sig_t sig_id);'''
39 4 Anthony Rowe
40 1 Anthony Rowe
This function is used to signal tasks that are waiting on events using nrk_event_wait().
41 1 Anthony Rowe
See example below.
42 1 Anthony Rowe
43 1 Anthony Rowe
44 4 Anthony Rowe
'''nrk_sig_mask_t nrk_event_wait(nrk_sig_mask_t event_mask);'''
45 1 Anthony Rowe
46 1 Anthony Rowe
This function will wait for a set events. nano-RK supports up to 31 signals. Each signal
47 1 Anthony Rowe
represents a bit in a 32 bit number (bit 0 is reserved) so it is possible to logically
48 1 Anthony Rowe
OR multiple signals together if you wish to wait on a combination of events. The 32
49 1 Anthony Rowe
bit number returned by nrk_event_wait() corresponds to the signal that was returned.
50 1 Anthony Rowe
When waiting on multiple signals, this should be used to determine which signal actually
51 1 Anthony Rowe
triggered the wakeup. All signals should be defined in the nrk_cfg.h file for each
52 1 Anthony Rowe
project.
53 1 Anthony Rowe
54 11 Anthony Rowe
55 11 Anthony Rowe
= Semaphores =
56 11 Anthony Rowe
57 11 Anthony Rowe
A semaphore is a protected variable and constitutes the classic method for restricting
58 11 Anthony Rowe
access to shared resources (e.g. storage,actuators etc) in a multiprogramming environment.
59 11 Anthony Rowe
Nano-RK implements semaphores and signals such that
60 11 Anthony Rowe
tasks that are suspended on an event or waiting for access to a semaphore will not be
61 12 Anthony Rowe
scheduled until the corresponding signal is sent or semaphore becomes available. For more information
62 12 Anthony Rowe
on using semaphores please refer to the basic_sem project that comes with the Nano-RK distribution: 
63 12 Anthony Rowe
http://www.nanork.org:8000/nano-RK/browser/nano-RK/projects/basic_sem/main.c
64 11 Anthony Rowe
65 16 Anthony Rowe
''Note that the Atmel ISA does not have a test-and-set instruction, so we provide a best effort implementation by disabling interrupts.'' 
66 16 Anthony Rowe
67 10 Anthony Rowe
'''nrk_sem_t* nrk_sem_create(uint8_t count, uint8_t ceiling_priority);'''
68 1 Anthony Rowe
69 10 Anthony Rowe
This function creates a semaphore resource, with a priority ceiling value used by the task when accessing the resource. This facilitates the Priority Ceiling Protocol Emulation (PCPE) algorithm used in Nano-RK to avoid priority inversion. ''count'' specifies the number of entries allowed into the critical section. ''ceiling_priority'' sets the ceiling value for the task; Note if
70 10 Anthony Rowe
using PCPE this should be the highest priority task accessing the critical section.  Below is an example of declaring and creating a semaphore:
71 10 Anthony Rowe
72 10 Anthony Rowe
{{{
73 10 Anthony Rowe
#!c
74 10 Anthony Rowe
   nrk_sem_t *my_semaphore;
75 10 Anthony Rowe
   ...
76 10 Anthony Rowe
   my_semaphore = nrk_sem_create(1,4);
77 10 Anthony Rowe
   if(my_semaphore==NULL) nrk_kprintf( PSTR("Error creating Semaphore\r\n" ));
78 10 Anthony Rowe
}}}
79 10 Anthony Rowe
80 10 Anthony Rowe
This created a semaphore with a count of 1 (also called a mutex or binary semaphore) with a priority ceiling value of 4.
81 1 Anthony Rowe
82 1 Anthony Rowe
'''int8_t nrk_sem_pend(nrk_sem_t *rsrc );''' 
83 1 Anthony Rowe
84 8 Anthony Rowe
Semaphore pend takes the address of the created semaphore and attempts to access the resource.  If the resource is available,
85 8 Anthony Rowe
pend will decrement the resource counter and allow the program to continue, otherwise pend will suspend until the resource is
86 8 Anthony Rowe
posted by another task. This can be used to protect critical sections of code. Below is an example of a task pending on a semaphore:
87 1 Anthony Rowe
88 1 Anthony Rowe
{{{
89 1 Anthony Rowe
#!c
90 1 Anthony Rowe
   nrk_kprintf( PSTR("Task accessing semaphore\r\n"));
91 1 Anthony Rowe
   v = nrk_sem_pend(my_semaphore);
92 1 Anthony Rowe
   if(v==NRK_ERROR) nrk_kprintf( PSTR("Error calling pend\r\n"));
93 1 Anthony Rowe
   nrk_kprintf( PSTR("Task is now holding semaphore\r\n"));
94 9 Anthony Rowe
}}}
95 9 Anthony Rowe
96 9 Anthony Rowe
'''int8_t nrk_sem_post(nrk_sem_t* rsrc);'''
97 9 Anthony Rowe
98 9 Anthony Rowe
Semaphore post takes the address of a created semaphore and releases access to the resource.
99 9 Anthony Rowe
This should be called after exiting a critical section that was pended.  Below is an example of a task posting a semaphore:
100 9 Anthony Rowe
101 1 Anthony Rowe
{{{
102 9 Anthony Rowe
#!c
103 9 Anthony Rowe
   v = nrk_sem_post(my_semaphore);
104 9 Anthony Rowe
   if(v==NRK_ERROR) nrk_kprintf( PSTR("Error calling post\r\n"));
105 9 Anthony Rowe
   nrk_kprintf( PSTR("Task released semaphore\r\n"));
106 8 Anthony Rowe
}}}
107 8 Anthony Rowe
108 11 Anthony Rowe
= Special Kernel Signals =
109 8 Anthony Rowe
110 18 Anthony Rowe
'''nrk_wakeup_signal'''
111 20 Anthony Rowe
112 19 Anthony Rowe
Sometimes it might be convenient to have a timeout associated with an nrk_event_wait() call.   This can be achieved using the kernel generated nrk_wakeup_signal.  This signal is sent on a per-task basis (not globally) when the task’s internal next-wakeup timer expires.  Normally, a task’s next wakeup is set for its next period, however this can be adjusted using the nrk_set_next_wakeup() function. nrk_wakeup_signal is created by the kernel during nrk_init().  In order for nrk_event_wait() to receive the nrk_wakeup_signal from a task it must simply be registered and muxed in like any other signal.  Note, each task has its own instance of the nrk_wakeup_signal.  Unlike other signals, it is not globally broadcast to all tasks.  See below for an example of how to use it as an event  timeout.
113 1 Anthony Rowe
114 19 Anthony Rowe
'''int8_t nrk_set_next_wakeup(nrk_time_t timeout);'''
115 20 Anthony Rowe
116 19 Anthony Rowe
This function sets the task's next wakeup timer.  It returns NRK_OK upon success and NRK_ERROR on failure.  This function does not
117 19 Anthony Rowe
suspend the task, it only changes when the next wakeup will happen if the task suspends on an event.  Calling other suspend functions like nrk_wait_until_next_period() will replace whatever wakeup value you might have previously set. 
118 18 Anthony Rowe
119 17 Anthony Rowe
{{{
120 17 Anthony Rowe
#!c
121 17 Anthony Rowe
   nrk_time_t timeout;
122 8 Anthony Rowe
123 17 Anthony Rowe
   timeout.secs=10;
124 17 Anthony Rowe
   timeout.nano_secs=0;
125 1 Anthony Rowe
   ...
126 1 Anthony Rowe
127 1 Anthony Rowe
   nrk_set_next_wakeup(timeout);
128 17 Anthony Rowe
   my_sigs=nrk_event_wait( SIG(signal_one) | SIG(nrk_wakeup_signal) );
129 17 Anthony Rowe
130 18 Anthony Rowe
   if(my_sigs==0)                        nrk_kprintf( PSTR( "Error calling nrk_event_wait()\r\n" ));
131 18 Anthony Rowe
   if(my_sigs & SIG(signal_one))         nrk_kprintf( PSTR( "Task got signal_one\r\n") );
132 18 Anthony Rowe
   if(my_sigs & SIG(nrk_wakeup_signal))  nrk_kprintf( PSTR( "Task got timeout signal! \r\n") );
133 17 Anthony Rowe
}}}
134 1 Anthony Rowe
135 1 Anthony Rowe
| [wiki:nrk-api Contents] | [wiki:nrk-api-device-drivers Device Drivers] |