Homework2_3Multithreads_YuwenSun

Dependencies:   mbed

Committer:
sun831011
Date:
Tue Nov 30 22:19:29 2010 +0000
Revision:
0:edab293d7652

        

Who changed what in which revision?

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