Henry Chen / Mbed 2 deprecated hw2_pt

Dependencies:   mbed

Committer:
henryicla
Date:
Wed Dec 01 02:00:40 2010 +0000
Revision:
0:09db827cab9c

        

Who changed what in which revision?

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