1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
/*
* Copyright (C) 1990-2000 by CERN/IT/PDP/DM
* All rights reserved
*/
#ifndef lint
static char sccsid[] = "$RCSfile: Csemaphore.c,v $ $Revision: 1.1 $ $Date: 2005/03/31 13:12:59 $ CERN/IT/PDP/DM";
#endif /* not lint */
/*//////////////////////////////////////////////////////////////////////
// File: Csemaphore.c
// --------------------------------------------------------------------
// This is a POSIX threads semaphore implementation. See the docs
// at http://dis.cs.umass.edu/~wagner/threads_html/tutorial.html
// for information on POSIX threads and how to use this lib.
// --------------------------------------------------------------------
// Written by: Tom A. Wagner
// wagner@cs.umass.edu
// Multi-Agent Systems Lab
// Department of Computer and Information Science
// University of Massachusetts
// Amherst, Massachusetts 01003.
//
// This code was written at the Multi-Agent Systems Lab. at the
// Department of Computer Science, University of Massachusetts,
// Amherst, MA 01003.
//
// Copyright (c) 1996 UMASS CS Dept. All rights are reserved.
//
// Development of this code was partially supported by:
// ONR grant N00014-92-J-1450
// NSF grant IRI-9523419
// DARPA grant, RaDEO program, 70NANB6H0074 as subcontractor for
// Boeing Helicoptor
////////////////////////////////////
//
// */
#include "Csemaphore.h"
/*
* function must be called prior to semaphore use.
*
*/
void
Csemaphore_init (CSemaphore * s,int value)
{
s->v = value;
}
/*
* function should be called when there is no longer a need for
* the semaphore.
*
*/
void
Csemaphore_destroy (CSemaphore * s)
{
if (Cthread_mutex_destroy ((s)) == -1)
do_error ("Error destroying Csemaphore mutex");
}
/*
* function increments the semaphore and signals any threads that
* are blocked waiting a change in the semaphore.
*
*/
int
Csemaphore_up (CSemaphore * s)
{
int value_after_op;
tw_pthread_mutex_lock ((void *)(s));
(s->v)++;
value_after_op = s->v;
tw_pthread_mutex_unlock ((void *)(s));
tw_pthread_cond_signal ((void *)(s));
return( value_after_op );
}
/*
* function decrements the semaphore and blocks if the semaphore is
* <= 0 until another thread signals a change.
*
*/
int
Csemaphore_down (CSemaphore * s)
{
int value_after_op;
tw_pthread_mutex_lock ((void *)(s));
while (s->v <= 0)
{
tw_pthread_cond_wait ((void *)(s));
}
(s->v)--;
value_after_op = s->v;
tw_pthread_mutex_unlock ((void *)(s));
return (value_after_op);
}
/*
* function does NOT block but simply decrements the semaphore.
* should not be used instead of down -- only for programs where
* multiple threads must up on a semaphore before another thread
* can go down, i.e., allows programmer to set the semaphore to
* a negative value prior to using it for synchronization.
*
*/
int
Csemaphore_decrement (CSemaphore * s)
{
int value_after_op;
tw_pthread_mutex_lock ((void *)(s));
s->v--;
value_after_op = s->v;
tw_pthread_mutex_unlock ((void *)(s));
return (value_after_op);
}
/*
* function returns the value of the semaphore at the time the
* critical section is accessed. obviously the value is not guarenteed
* after the function unlocks the critical section. provided only
* for casual debugging, a better approach is for the programmar to
* protect one semaphore with another and then check its value.
* an alternative is to simply record the value returned by semaphore_up
* or semaphore_down.
*
*/
int
Csemaphore_value (CSemaphore * s)
{
/* not for sync */
int value_after_op;
tw_pthread_mutex_lock ((void *)(s));
value_after_op = s->v;
tw_pthread_mutex_unlock ((void *)(s));
return (value_after_op);
}
/* -------------------------------------------------------------------- */
/* The following functions replace standard library functions in that */
/* they exit on any error returned from the system calls. Saves us */
/* from having to check each and every call above. */
/* -------------------------------------------------------------------- */
int
tw_pthread_mutex_unlock(void *m)
{
int return_value;
if ((return_value = Cthread_mutex_unlock (m)) == -1)
do_error ("Cthread_mutex_unlock");
return (return_value);
}
int
tw_pthread_mutex_lock (void * m)
{
int return_value;
if ((return_value = Cthread_mutex_lock (m)) == -1)
do_error ("Cthread_mutex_lock");
return (return_value);
}
int
tw_pthread_cond_wait (void * c)
{
int return_value;
if ((return_value = Cthread_cond_wait (c)) == -1)
do_error ("Cthread_cond_wait");
return (return_value);
}
int
tw_pthread_cond_signal (void * c)
{
int return_value;
if ((return_value = Cthread_cond_signal (c)) == -1)
do_error ("pthread_cond_signal");
return (return_value);
}
/*
* function just prints an error message and exits
*
*/
void
do_error (char *msg)
{
perror (msg);
exit (1);
}
|