XIAOHUI TAO / Mbed 2 deprecated hw2_protothread
Committer:
taoxh
Date:
Tue Nov 30 23:53:06 2010 +0000
Revision:
0:ee91220d7bea
HW2 PROTOTHREAD

Who changed what in which revision?

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