1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2009 FRESCOR consortium partners:
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
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
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
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FOSA (Frsh Operating System Adaption)
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.
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 // // /******/ //////// // //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
69 #include "fosa_mutexes_and_condvars.h"
74 #include <misc/error_checks.h>
76 #include "fosa_time.h"
78 /*******************************************************
79 * Mutexes with priority ceiling
80 ******************************************************/
85 * Initialize a frsh mutex
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.
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
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
101 int fosa_mutex_init(fosa_mutex_t *mutex, int prioceiling)
103 pthread_mutexattr_t attr;
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;
111 CHK(pthread_mutexattr_setprotocol(&attr,PTHREAD_PRIO_PROTECT));
112 ret_value=pthread_mutexattr_setprioceiling(&attr,prioceiling);
116 ret_value=pthread_mutex_init(mutex,&attr);
118 // destroy the mutex attributes object
119 pthread_mutexattr_destroy(&attr);
125 * fosa_mutex_destroy()
127 * Destroy a frsh mutex
129 * The mutex pointed to by mutex is destroyed
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)
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
139 int fosa_mutex_destroy(fosa_mutex_t *mutex)
141 return pthread_mutex_destroy(mutex);
145 * fosa_mutex_set_prioceiling()
147 * Dynamically set the priority ceiling of a mutex
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
155 * Returns 0 if successful; otherwise it returns an error code:
156 * EINVAL: the value of mutex or prioceiling is invalid
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
162 int fosa_mutex_set_prioceiling
163 (fosa_mutex_t *mutex, int new_ceiling, int *old_ceiling)
165 return pthread_mutex_setprioceiling(mutex,new_ceiling,old_ceiling);
169 * fosa_mutex_get_prioceiling()
171 * Dynamically get the priority ceiling of a mutex
173 * This function copies into the variable pointed to by ceiling the
174 * current priority ceiling of the mutex referenced by mutex
176 * Returns 0 if successful; otherwise it returns an error code:
177 * EINVAL: the value of mutex is invalid
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
183 int fosa_mutex_get_prioceiling(const fosa_mutex_t *mutex, int *ceiling)
185 return pthread_mutex_getprioceiling(mutex,ceiling);
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.
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
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
207 int fosa_mutex_lock(fosa_mutex_t *mutex)
209 return pthread_mutex_lock(mutex);
213 * fosa_mutex_trylock()
215 * Try locking a mutex
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
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
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
230 int fosa_mutex_trylock(fosa_mutex_t *mutex)
232 return pthread_mutex_trylock(mutex);
236 * fosa_mutex_unlock()
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.
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
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
253 int fosa_mutex_unlock(fosa_mutex_t *mutex)
255 return pthread_mutex_unlock(mutex);
259 /**********************
260 * Condition variables
261 *********************/
266 * Initiatize a condition variable
268 * The condition variable referenced by cond is initialized with
269 * the attributes required by the FOSA implementation.
271 * Returns 0 if successful; otherwise it returns an error code:
272 * EAGAIN: the system lacked the necessary resources to create the
274 * ENOMEM: Insufficient memory exists to initialize the condition variable
275 * EBUSY: The system has detected an attempt to reinitialize the
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
282 int fosa_cond_init(fosa_cond_t *cond)
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);
290 * fosa_cond_destroy()
292 * Destroy a condition variable
294 * The condition variable pointed to by cond is destroyed
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)
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
304 int fosa_cond_destroy(fosa_cond_t *cond)
306 return pthread_cond_destroy(cond);
312 * Signal a condition variable
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
318 * Returns 0 if successful; otherwise it returns an error code:
319 * EINVAL: the value of cond is invalid
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
325 int fosa_cond_signal(fosa_cond_t *cond)
327 return pthread_cond_signal(cond);
331 * fosa_cond_broadcast()
333 * Broadcast a condition variable
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.
339 * Returns 0 if successful; otherwise it returns an error code:
340 * EINVAL: the value of cond is invalid
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
346 int fosa_cond_broadcast(fosa_cond_t *cond)
348 return pthread_cond_broadcast(cond);
354 * Wait at a condition variable
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.
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
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
372 int fosa_cond_wait(fosa_cond_t *cond, fosa_mutex_t *mutex)
374 return pthread_cond_wait(cond,mutex);
378 * fosa_cond_timedwait()
380 * Wait at a condition variable, with a timeout
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.
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
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
396 int fosa_cond_timedwait(fosa_cond_t *cond, fosa_mutex_t *mutex,
397 const fosa_abs_time_t *abstime)
399 struct timespec abstime_tspec;
401 abstime_tspec = fosa_abs_time_to_timespec(*abstime);
403 return pthread_cond_timedwait(cond,mutex, &abstime_tspec);