File: Csemaphore.c

package info (click to toggle)
lcgdm 1.10.0-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 17,532 kB
  • sloc: ansic: 226,887; sh: 13,562; perl: 11,575; python: 11,572; cpp: 5,716; sql: 1,824; makefile: 1,301; fortran: 113
file content (216 lines) | stat: -rw-r--r-- 5,143 bytes parent folder | download | duplicates (8)
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);
}