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