Contiki 3.x
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
core
sys
pt-sem.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2004, Swedish Institute of Computer Science.
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the Institute nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*
29
* This file is part of the Contiki operating system.
30
*
31
* Author: Adam Dunkels <adam@sics.se>
32
*
33
*/
34
35
/**
36
* \addtogroup pt
37
* @{
38
*/
39
40
/**
41
* \defgroup ptsem Protothread semaphores
42
* @{
43
*
44
* This module implements counting semaphores on top of
45
* protothreads. Semaphores are a synchronization primitive that
46
* provide two operations: "wait" and "signal". The "wait" operation
47
* checks the semaphore counter and blocks the thread if the counter
48
* is zero. The "signal" operation increases the semaphore counter but
49
* does not block. If another thread has blocked waiting for the
50
* semaphore that is signaled, the blocked thread will become
51
* runnable again.
52
*
53
* Semaphores can be used to implement other, more structured,
54
* synchronization primitives such as monitors and message
55
* queues/bounded buffers (see below).
56
*
57
* The following example shows how the producer-consumer problem, also
58
* known as the bounded buffer problem, can be solved using
59
* protothreads and semaphores. Notes on the program follow after the
60
* example.
61
*
62
\code
63
#include "pt-sem.h"
64
65
#define NUM_ITEMS 32
66
#define BUFSIZE 8
67
68
static struct pt_sem mutex, full, empty;
69
70
PT_THREAD(producer(struct pt *pt))
71
{
72
static int produced;
73
74
PT_BEGIN(pt);
75
76
for(produced = 0; produced < NUM_ITEMS; ++produced) {
77
78
PT_SEM_WAIT(pt, &full);
79
80
PT_SEM_WAIT(pt, &mutex);
81
add_to_buffer(produce_item());
82
PT_SEM_SIGNAL(pt, &mutex);
83
84
PT_SEM_SIGNAL(pt, &empty);
85
}
86
87
PT_END(pt);
88
}
89
90
PT_THREAD(consumer(struct pt *pt))
91
{
92
static int consumed;
93
94
PT_BEGIN(pt);
95
96
for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
97
98
PT_SEM_WAIT(pt, &empty);
99
100
PT_SEM_WAIT(pt, &mutex);
101
consume_item(get_from_buffer());
102
PT_SEM_SIGNAL(pt, &mutex);
103
104
PT_SEM_SIGNAL(pt, &full);
105
}
106
107
PT_END(pt);
108
}
109
110
PT_THREAD(driver_thread(struct pt *pt))
111
{
112
static struct pt pt_producer, pt_consumer;
113
114
PT_BEGIN(pt);
115
116
PT_SEM_INIT(&empty, 0);
117
PT_SEM_INIT(&full, BUFSIZE);
118
PT_SEM_INIT(&mutex, 1);
119
120
PT_INIT(&pt_producer);
121
PT_INIT(&pt_consumer);
122
123
PT_WAIT_THREAD(pt, producer(&pt_producer) &
124
consumer(&pt_consumer));
125
126
PT_END(pt);
127
}
128
\endcode
129
*
130
* The program uses three protothreads: one protothread that
131
* implements the consumer, one thread that implements the producer,
132
* and one protothread that drives the two other protothreads. The
133
* program uses three semaphores: "full", "empty" and "mutex". The
134
* "mutex" semaphore is used to provide mutual exclusion for the
135
* buffer, the "empty" semaphore is used to block the consumer is the
136
* buffer is empty, and the "full" semaphore is used to block the
137
* producer is the buffer is full.
138
*
139
* The "driver_thread" holds two protothread state variables,
140
* "pt_producer" and "pt_consumer". It is important to note that both
141
* these variables are declared as <i>static</i>. If the static
142
* keyword is not used, both variables are stored on the stack. Since
143
* protothreads do not store the stack, these variables may be
144
* overwritten during a protothread wait operation. Similarly, both
145
* the "consumer" and "producer" protothreads declare their local
146
* variables as static, to avoid them being stored on the stack.
147
*
148
*
149
*/
150
151
/**
152
* \file
153
* Counting semaphores implemented on protothreads
154
* \author
155
* Adam Dunkels <adam@sics.se>
156
*
157
*/
158
159
#ifndef PT_SEM_H_
160
#define PT_SEM_H_
161
162
#include "
sys/pt.h
"
163
164
struct
pt_sem {
165
unsigned
int
count;
166
};
167
168
/**
169
* Initialize a semaphore
170
*
171
* This macro initializes a semaphore with a value for the
172
* counter. Internally, the semaphores use an "unsigned int" to
173
* represent the counter, and therefore the "count" argument should be
174
* within range of an unsigned int.
175
*
176
* \param s (struct pt_sem *) A pointer to the pt_sem struct
177
* representing the semaphore
178
*
179
* \param c (unsigned int) The initial count of the semaphore.
180
* \hideinitializer
181
*/
182
#define PT_SEM_INIT(s, c) (s)->count = c
183
184
/**
185
* Wait for a semaphore
186
*
187
* This macro carries out the "wait" operation on the semaphore. The
188
* wait operation causes the protothread to block while the counter is
189
* zero. When the counter reaches a value larger than zero, the
190
* protothread will continue.
191
*
192
* \param pt (struct pt *) A pointer to the protothread (struct pt) in
193
* which the operation is executed.
194
*
195
* \param s (struct pt_sem *) A pointer to the pt_sem struct
196
* representing the semaphore
197
*
198
* \hideinitializer
199
*/
200
#define PT_SEM_WAIT(pt, s) \
201
do { \
202
PT_WAIT_UNTIL(pt, (s)->count > 0); \
203
--(s)->count; \
204
} while(0)
205
206
/**
207
* Signal a semaphore
208
*
209
* This macro carries out the "signal" operation on the semaphore. The
210
* signal operation increments the counter inside the semaphore, which
211
* eventually will cause waiting protothreads to continue executing.
212
*
213
* \param pt (struct pt *) A pointer to the protothread (struct pt) in
214
* which the operation is executed.
215
*
216
* \param s (struct pt_sem *) A pointer to the pt_sem struct
217
* representing the semaphore
218
*
219
* \hideinitializer
220
*/
221
#define PT_SEM_SIGNAL(pt, s) ++(s)->count
222
223
#endif
/* PT_SEM_H_ */
224
225
/** @} */
226
/** @} */
227
pt.h
Protothreads implementation.
Generated on Sun Nov 30 2014 09:58:54 for Contiki 3.x by
1.8.5