]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/fosa_mutexes_and_condvars.c
59acd210c2d6ba51b5cac20ef4e5f033bc0c0967
[frescor/fosa.git] / src_marte / fosa_mutexes_and_condvars.c
1 //----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politecnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org
17 //
18 //        The FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 // This file is part of FOSA (Frsh Operating System Abstraction)
32 //
33 // FOSA is free software; you can redistribute it and/or modify it
34 // under terms of the GNU General Public License as published by the
35 // Free Software Foundation; either version 2, or (at your option) any
36 // later version.  FOSA is distributed in the hope that it will be
37 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
38 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 // General Public License for more details. You should have received a
40 // copy of the GNU General Public License along with FOSA; see file
41 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
42 // Cambridge, MA 02139, USA.
43 //
44 // As a special exception, including FOSA header files in a file,
45 // instantiating FOSA generics or templates, or linking other files
46 // with FOSA objects to produce an executable application, does not
47 // by itself cause the resulting executable application to be covered
48 // by the GNU General Public License. This exception does not
49 // however invalidate any other reasons why the executable file might be
50 // covered by the GNU Public License.
51 // -----------------------------------------------------------------------
52 //fosa_mutexes_and_condvars.c
53 //==============================================
54 //  ********  ******    ********  **********
55 //  **///// /**    **  **//////  /**     /**
56 //  **      /**    ** /**        /**     /**
57 //  ******* /**    ** /********* /**********
58 //  **////  /**    ** ////////** /**//////**
59 //  **      /**    **        /** /**     /**
60 //  **      /**    **  ********  /**     /**
61 //  //       /******/  ////////   //      //
62 //
63 // FOSA(Frescor Operating System Adaptation layer)
64 //================================================
65
66 #include "fosa_mutexes_and_condvars.h"
67
68 #include <pthread.h>
69 #include <stdio.h>
70
71 #include <misc/error_checks.h>
72
73
74
75 /*******************************************************
76  * Mutexes with priority ceiling
77  ******************************************************/
78
79 /**
80  * fosa_mutex_init()
81  *
82  * Initialize a frsh mutex
83  *
84  * The mutex pointed to by mutex is initialized as a mutex using
85  * the priority ceiling protocol. A priority ceiling of prioceiling
86  * is assigned to this mutex.
87  *
88  * Returns 0 if successful; otherwise it returns an error code:
89  *    EINVAL: the value of prioceiling is invalid
90  *    EAGAIN: the system lacked the necessary resources to create the mutex
91  *    ENOMEM: Insufficient memory exists to initialize the mutex
92  *    EBUSY:  The system has detected an attempt to reinitialize the mutex
93  *
94  * Alternatively, in case of error the implementation is allowed to
95  * notify it to the system console and then terminate the FRSH
96  * implementation and dependant applications
97  **/
98 int fosa_mutex_init(frsh_mutex_t *mutex, int prioceiling)
99 {
100   pthread_mutexattr_t attr;
101   int ret_value;
102
103   // create the attributes object and set the mutex to use the
104   // priority ceiling protocol and the desired priority ceiling
105   ret_value=pthread_mutexattr_init(&attr);
106   if (ret_value!=0) return ret_value;
107
108   CHK(pthread_mutexattr_setprotocol(&attr,PTHREAD_PRIO_PROTECT));
109   ret_value=pthread_mutexattr_setprioceiling(&attr,prioceiling);
110
111   if (ret_value==0) {
112     // create the mutex
113     ret_value=pthread_mutex_init(mutex,&attr);
114   }
115   // destroy the mutex attributes object
116   pthread_mutexattr_destroy(&attr);
117
118   return ret_value;
119 }
120
121 /**
122  * fosa_mutex_destroy()
123  *
124  * Destroy a frsh mutex
125  *
126  * The mutex pointed to by mutex is destroyed
127  *
128  * Returns 0 if successful; otherwise it returns an error code:
129  *    EINVAL: the value of mutex is invalid
130  *    EBUSY:  The mutex is in use (is locked)
131  *
132  * Alternatively, in case of error the implementation is allowed to
133  * notify it to the system console and then terminate the FRSH
134  * implementation and dependant applications
135  **/
136 int fosa_mutex_destroy(frsh_mutex_t *mutex)
137 {
138   return pthread_mutex_destroy(mutex);
139 }
140
141 /**
142  * fosa_mutex_set_prioceiling()
143  *
144  * Dynamically set the priority ceiling of a mutex
145  *
146  * This function locks the mutex (blocking the calling thread if
147  * necessary) and after it is locked it changes its priority ceiling
148  * to the value specified by new_ceiling, and then it unlocks the
149  * mutex. The previous value of the ceiling is returned in
150  * old_ceiling.
151  *
152  * Returns 0 if successful; otherwise it returns an error code:
153  *     EINVAL: the value of mutex or prioceiling is invalid
154  *
155  * Alternatively, in case of error the implementation is allowed to
156  * notify it to the system console and then terminate the FRSH
157  * implementation and dependant applications
158  **/
159 int fosa_mutex_set_prioceiling
160    (frsh_mutex_t *mutex, int new_ceiling, int *old_ceiling)
161 {
162   return pthread_mutex_setprioceiling(mutex,new_ceiling,old_ceiling);
163 }
164
165 /**
166  * fosa_mutex_get_prioceiling()
167  *
168  * Dynamically get the priority ceiling of a mutex
169  *
170  * This function copies into the variable pointed to by ceiling the
171  * current priority ceiling of the mutex referenced by mutex
172  *
173  * Returns 0 if successful; otherwise it returns an error code:
174  *     EINVAL: the value of mutex is invalid
175  *
176  * Alternatively, in case of error the implementation is allowed to
177  * notify it to the system console and then terminate the FRSH
178  * implementation and dependant applications
179  **/
180 int fosa_mutex_get_prioceiling(const frsh_mutex_t *mutex, int *ceiling)
181 {
182   return pthread_mutex_getprioceiling(mutex,ceiling);
183 }
184
185 /**
186  * fosa_mutex_lock()
187  *
188  * Lock a mutex
189  *
190  * This function locks the mutex specified by mutex. If it is already
191  * locked, the calling thread blocks until the mutex becomes
192  * available. The operation returns with the mutex in the locked
193  * state, with the calling thread as its owner.
194  *
195  * Returns 0 if successful; otherwise it returns an error code:
196  *    EINVAL: the value of mutex is invalid, or the priority of the
197  *            calling thread is higher than the priority ceiling of the mutex
198  *    EDEADLK: the current thread already owns this mutex
199  *
200  * Alternatively, in case of error the implementation is allowed to
201  * notify it to the system console and then terminate the FRSH
202  * implementation and dependant applications
203  **/
204 int fosa_mutex_lock(frsh_mutex_t *mutex)
205 {
206   return pthread_mutex_lock(mutex);
207 }
208
209 /**
210  * fosa_mutex_trylock()
211  *
212  * Try locking a mutex
213  *
214  * This function is identical to fosa_mutex_lock() except that if the
215  * mutex is already locked the call returns immediately with an error
216  * indication.
217  *
218  * Returns 0 if successful; otherwise it returns an error code:
219  *    EINVAL: the value of mutex is invalid, or the priority of the
220  *            calling thread is higher than the priority ceiling of the mutex
221  *    EBUSY: the mutex was already locked
222  *
223  * Alternatively, except for EBUSY, in case of error the
224  * implementation is allowed to notify it to the system console and
225  * then terminate the FRSH implementation and dependant applications
226  **/
227 int fosa_mutex_trylock(frsh_mutex_t *mutex)
228 {
229   return pthread_mutex_trylock(mutex);
230 }
231
232 /**
233  * fosa_mutex_unlock()
234  *
235  * Unlock a mutex
236  *
237  * This function must be called by the owner of the mutex referenced
238  * by mutex, to unlock it. If there are threads blocked on the mutex
239  * the mutex becomes available and the highest priority thread is
240  * awakened to acquire the mutex.
241  *
242  * Returns 0 if successful; otherwise it returns an error code:
243  *     EINVAL: the value of mutex is invalid
244  *     EPERM: the calling thread is not the owner of the mutex
245  *
246  * Alternatively, except for EBUSY, in case of error the
247  * implementation is allowed to notify it to the system console and
248  * then terminate the FRSH implementation and dependant applications
249  **/
250 int fosa_mutex_unlock(frsh_mutex_t *mutex)
251 {
252   return pthread_mutex_unlock(mutex);
253 }
254
255
256 /**********************
257  * Condition variables
258  *********************/
259
260 /**
261  * fosa_cond_init()
262  *
263  * Initiatize a condition variable
264  *
265  * The condition variable referenced by cond is initialized with
266  * the attributes required by the FOSA implementation.
267  *
268  *  Returns 0 if successful; otherwise it returns an error code:
269  *     EAGAIN: the system lacked the necessary resources to create the
270  *             condition variable
271  *     ENOMEM: Insufficient memory exists to initialize the condition variable
272  *     EBUSY:  The system has detected an attempt to reinitialize the
273  *             condition variable
274  *
275  * Alternatively, in case of error the implementation is allowed to
276  * notify it to the system console and then terminate the FRSH
277  * implementation and dependant applications
278  **/
279 int fosa_cond_init(fosa_cond_t *cond)
280 {
281   // initialize condition variable with default attributes
282   // TODO: cond var attr timer to monotonic when supported by marte
283   return pthread_cond_init(cond,NULL);
284 }
285
286 /**
287  * fosa_cond_destroy()
288  *
289  * Destroy a condition variable
290  *
291  * The condition variable pointed to by cond is destroyed
292  *
293  * Returns 0 if successful; otherwise it returns an error code:
294  *     EINVAL: the value of cond is invalid
295  *     EBUSY:  The condition variable is in use (a thread is waiting on it)
296  *
297  * Alternatively, in case of error the implementation is allowed to
298  * notify it to the system console and then terminate the FRSH
299  * implementation and dependant applications
300  **/
301 int fosa_cond_destroy(fosa_cond_t *cond)
302 {
303   return pthread_cond_destroy(cond);
304 }
305
306 /**
307  * fosa_cond_signal()
308  *
309  * Signal a condition variable
310  *
311  * This call unblocks at least one of the threads that are waiting on
312  * the condition variable referenced by cond. If there are no threads
313  * waiting, the function has no effect
314  *
315  * Returns 0 if successful; otherwise it returns an error code:
316  *     EINVAL: the value of cond is invalid
317  *
318  * Alternatively, in case of error the implementation is allowed to
319  * notify it to the system console and then terminate the FRSH
320  * implementation and dependant applications
321  **/
322 int fosa_cond_signal(fosa_cond_t *cond)
323 {
324   return pthread_cond_signal(cond);
325 }
326
327 /**
328  * fosa_cond_broadcast()
329  *
330  * Broadcast a condition variable
331  *
332  * This call unblocks all of the threads that are waiting on the
333  * condition variable referenced by cond. If there are no threads
334  * waiting, the function has no effect.
335  *
336  * Returns 0 if successful; otherwise it returns an error code:
337  *     EINVAL: the value of cond is invalid
338  *
339  * Alternatively, in case of error the implementation is allowed to
340  * notify it to the system console and then terminate the FRSH
341  * implementation and dependant applications
342  **/
343 int fosa_cond_broadcast(fosa_cond_t *cond)
344 {
345   return pthread_cond_broadcast(cond);
346 }
347
348 /**
349  * fosa_cond_wait()
350  *
351  * Wait at a condition variable
352  *
353  * This call is used to block on the condition variable referenced by
354  * cond. It shall be called with the mutex referenced by mutex
355  * locked. The function releases the mutex and blocks the calling
356  * thread until the condition is signalled by some other thread and
357  * the calling thread is awakened. Then it locks the mutex and
358  * returns with the mutex locked by the calling thread.
359  *
360  * Returns 0 if successful; otherwise it returns an error code:
361  *    EINVAL: the value of cond or mutex is invalid, or different
362  *            mutexes were used for concurrent wait operations on cond, or
363  *            the mutex was not owned by the calling thread
364  *
365  * Alternatively, in case of error the implementation is allowed to
366  * notify it to the system console and then terminate the FRSH
367  * implementation and dependant applications
368  **/
369 int fosa_cond_wait(fosa_cond_t *cond, frsh_mutex_t *mutex)
370 {
371   return pthread_cond_wait(cond,mutex);
372 }
373
374 /**
375  * fosa_cond_timedwait()
376  *
377  * Wait at a condition variable, with a timeout
378  *
379  * This function is equal to fosa_cond_wait(), except that the maximum
380  * wait time is limited to the absolute time referenced by abstime, as
381  * measured by the FOSA_CLOCK_ABSOLUTE clock.
382  *
383  * Returns 0 if successful; otherwise it returns an error code:
384  *     EINVAL: the value of cond or mutex or abstime is invalid, or different
385  *             mutexes were used for concurrent wait operations on cond, or
386  *             the mutex was not owned by the calling thread
387  *     ETIMEDOUT: the timeout expired
388  *
389  * Alternatively, except for ETIMEDOUT, in case of error the
390  * implementation is allowed to notify it to the system console and
391  * then terminate the FRSH implementation and dependant applications
392  **/
393 int fosa_cond_timedwait(fosa_cond_t *cond, frsh_mutex_t *mutex,
394       const struct timespec *abstime)
395 {
396   return pthread_cond_timedwait(cond,mutex,abstime);
397 }