]> rtime.felk.cvut.cz Git - frescor/fosa.git/blobdiff - src_partikle/fosa_threads_and_signals.c
Updating header text in FOSA files for the incoming final project
[frescor/fosa.git] / src_partikle / fosa_threads_and_signals.c
index 6075b97d281308f6e448e80d750165d433f254e0..b05709add74b1628e12cad5a40bad7839b44b68a 100644 (file)
-/** fosa_threads_and_signals.h
- *
- * < description >
- * < author >
- * < date >
- */
+// -----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2009 FRESCOR consortium partners:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politécnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org for a link to partners' websites
+//
+//           FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+//   FSF API web pages: http://marte.unican.es/fsf/docs
+//                      http://shark.sssup.it/contrib/first/docs/
+//
+//   This file is part of FOSA (Frsh Operating System Adaption)
+//
+//  FOSA is free software; you can redistribute it and/or modify it
+//  under terms of the GNU General Public License as published by the
+//  Free Software Foundation; either version 2, or (at your option) any
+//  later version.  FOSA is distributed in the hope that it will be
+//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+//  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//  General Public License for more details. You should have received a
+//  copy of the GNU General Public License along with FOSA; see file
+//  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+//  Cambridge, MA 02139, USA.
+//
+//  As a special exception, including FOSA header files in a file,
+//  instantiating FOSA generics or templates, or linking other files
+//  with FOSA objects to produce an executable application, does not
+//  by itself cause the resulting executable application to be covered
+//  by the GNU General Public License. This exception does not
+//  however invalidate any other reasons why the executable file might be
+//  covered by the GNU Public License.
+// -----------------------------------------------------------------------
+//==============================================
+//  ********  ******    ********  **********
+//  **///// /**    **  **//////  /**     /**
+//  **      /**    ** /**        /**     /**
+//  ******* /**    ** /********* /**********
+//  **////  /**    ** ////////** /**//////**
+//  **      /**    **        /** /**     /**
+//  **      /**    **  ********  /**     /**
+//  //       /******/  ////////   //      // 
+//
+// FOSA(Frescor Operating System Adaptation layer)
+//================================================
 
+#include <fosa_configuration_parameters.h>
 #include <fosa_threads_and_signals.h>
+#include <fosa_time.h>
+#include <unistd.h>
+#include <signal.h>
+
+#define TRACE(str, args...) printf ("%d: %s: " str, __LINE__, __func__, ##args)
 
 /*************************
  * Thread identification
  *************************/ 
-bool fosa_thread_equal(frsh_thread_id_t t1, frsh_thread_id_t t2);
-frsh_thread_id_t fosa_thread_self();
+bool fosa_thread_equal(fosa_thread_id_t t1, fosa_thread_id_t t2)
+{
+       return pthread_equal (t1, t2);
+}
+
+fosa_thread_id_t fosa_thread_self()
+{
+       return pthread_self();
+}
+
+/*************************
+ * Thread attributes
+ *************************/ 
+
+int fosa_thread_attr_init(fosa_thread_attr_t *attr)
+{
+  return pthread_attr_init (attr);
+}
+
+int fosa_thread_attr_destroy(fosa_thread_attr_t *attr)
+{
+  return pthread_attr_destroy (attr);
+}
+
+int fosa_thread_attr_set_stacksize(fosa_thread_attr_t *attr,
+                                  size_t stacksize)
+{
+  return pthread_attr_setstacksize (attr, stacksize);
+}
+
+
+int fosa_thread_attr_get_stacksize(const fosa_thread_attr_t *attr, 
+                                  size_t *stacksize)
+{
+  return pthread_attr_getstacksize (attr, stacksize);
+}
+
+
 /*************************
  * Thread creation and termination
  *************************/ 
-int fosa_thread_create
-                (frsh_thread_id_t *tid, const frsh_thread_attr_t *attr, 
-                 frsh_thread_code_t code, void * arg);
+ int fosa_thread_create
+     (fosa_thread_id_t *tid, 
+      const fosa_thread_attr_t *attr, 
+      fosa_thread_code_t code, 
+      void * arg)
+{
+  return pthread_create (tid, attr, code, arg);
+}
 
 
 /**************************************************
  * Thread-specific data
  *  (extended with access from a different thread)
  **************************************************/ 
-int fosa_key_create(int *key);
-int fosa_key_destroy(int key);
-int fosa_thread_set_specific_data
-                (int key, frsh_thread_id_t tid, const void * value);
-int fosa_thread_get_specific_data(int key, frsh_thread_id_t tid, 
-                                  void ** value);
+int fosa_key_create(int *key)
+{
+       switch (pthread_key_create (key, NULL)) {
+               case 0:
+                       break;
+               case ENOMEM:
+                       return ENOMEM;
+                       break;
+               case EAGAIN:
+               default:
+                       return FOSA_EINVAL;
+       }
+
+       if (*key >= FOSA_MAX_KEYS + 1) {
+               pthread_key_delete (*key);
+               return FOSA_EINVAL;
+       }
+       
+       return 0;
+}
+
+int fosa_key_destroy(int key)
+{
+       if (key < 0 || key >= FOSA_MAX_KEYS + 1)
+               return FOSA_EINVAL;
+       
+       return pthread_key_delete (key);
+}
+
+ int fosa_thread_set_specific_data
+     (int key, fosa_thread_id_t tid, const void * value)
+{
+       if (key < 0 || key >= FOSA_MAX_KEYS + 1)
+               return FOSA_EINVAL;
+       
+       return pthread_setspecific_for (key, tid, value);
+}
+
+int fosa_thread_get_specific_data(int key, fosa_thread_id_t tid, 
+                                 void ** value)
+{
+       if (key < 0 || key >= FOSA_MAX_KEYS + 1)
+               return FOSA_EINVAL;
+
+       return pthread_getspecific_from (key, tid, value);
+}
 
 /**********************
  * Thread scheduling
  **********************/
-int fosa_get_priority_max();
-int fosa_get_priority_min();
-int fosa_thread_attr_set_prio(frsh_thread_attr_t *attr, int prio);
-int fosa_thread_attr_get_prio
-                (const frsh_thread_attr_t *attr, int *prio);
-int fosa_thread_set_prio(frsh_thread_id_t tid, int prio);
-int fosa_thread_get_prio (frsh_thread_id_t tid, int *prio);
+// PaRTiKle uses decreasing values for increasing priority (0 -> maxprio)
+
+inline int fosa2prtk (int prio, int urg)
+{
+  return ((prio & 0x3f) << 4) + (urg & 0xf);
+}
+
+static inline int prtk2fprio (int prio)
+{
+  return (prio >> 4) & 0x3f;
+}
+
+static inline int prtk2furg (int prio)
+{
+  return prio & 0xf;
+}
+
+
+int fosa_get_priority_max()
+{
+       return prtk2fprio (sched_get_priority_min (SCHED_FIFO));
+}
+
+int fosa_get_priority_min()
+{
+       return prtk2fprio (sched_get_priority_max (SCHED_FIFO));
+}
+
+int fosa_thread_attr_set_prio(fosa_thread_attr_t *attr, int prio)
+{
+       struct sched_param sp;
+       
+       if (prio > fosa_get_priority_max () || prio < fosa_get_priority_min ())
+               return EINVAL;
+       
+       sp.sched_priority = sched_get_priority_min (SCHED_FIFO) - fosa2prtk (prio, 0);
+       
+       return pthread_attr_setschedparam (attr, &sp);
+}
+
+ int fosa_thread_attr_get_prio
+     (const fosa_thread_attr_t *attr, int *prio)
+{
+       struct sched_param sp;
+       
+       pthread_attr_getschedparam (attr, &sp);
+       
+       *prio = prtk2fprio (sched_get_priority_min (SCHED_FIFO) - sp.sched_priority);
+       
+       return 0;
+}
+
+int fosa_thread_set_prio(fosa_thread_id_t tid, int prio)
+{
+       struct sched_param sp;
+       int policy;
+
+       if (prio > fosa_get_priority_max () || prio < fosa_get_priority_min ())
+               return EINVAL;
+       
+       pthread_getschedparam (tid, &policy, &sp);
+       sp.sched_priority = sched_get_priority_min (SCHED_FIFO) - fosa2prtk (prio, 0);
+       
+       return pthread_setschedparam (tid, policy, &sp);
+}
+       
+int fosa_thread_get_prio (fosa_thread_id_t tid, int *prio)
+{
+       struct sched_param sp;
+       int policy;
+       
+       pthread_getschedparam (tid, &policy, &sp);
+       *prio = sched_get_priority_min (SCHED_FIFO) - sp.sched_priority;
+       
+       return 0;
+}
 
 
 /*************
  * Signals
  *************/
-int fosa_set_accepted_signals(frsh_signal_t set[], int size);
+int fosa_set_accepted_signals(fosa_signal_t set[], int size)
+{
+       int i;
+       sigset_t accept_set;
+       struct sigaction act;
+       
+//     printf ("%d: %s: limits=[%d, %d]\n", __LINE__, __FUNCTION__,
+//             FOSA_SIGNAL_MIN, FOSA_SIGNAL_MAX);
+
+       if (size < 0) 
+               return EINVAL;
+       
+       sigemptyset (&accept_set);
+       act.sa_mask = accept_set;
+       act.sa_flags = SA_SIGINFO;
+       act.sa_handler = SIG_DFL;
+       
+//     printf ("%d: %s: add signals\n", __LINE__, __FUNCTION__);
+       for (i = 0; i < size; i ++) {
+//       printf ("%d: %s: signal=%d \n", __LINE__, __FUNCTION__, set[i]);
+         
+         if (FOSA_SIGNAL_MIN > set [i] || set [i] > FOSA_SIGNAL_MAX)
+                       return EINVAL;
+       
+//       printf ("%d: %s: sigaction\n", __LINE__, __FUNCTION__);
+         sigaction (set [i], &act, NULL);
+               sigaddset (&accept_set, set [i]);
+       }
+
+//     printf ("%d: %s: pthread_sigmask\n", __LINE__, __FUNCTION__);
+       assert (!pthread_sigmask (SIG_BLOCK, &accept_set, NULL));
+       return 0;
+}
+
+
 int fosa_signal_queue
-               (frsh_signal_t signal, frsh_signal_info_t info,
-                frsh_thread_id_t receiver);
+    (fosa_signal_t signal, fosa_signal_info_t info,
+     fosa_thread_id_t receiver)
+{
+       union sigval nfo = (union sigval) info.sival_ptr;
+       
+       if (sigqueue (1, signal, nfo))
+               return errno;
+       else
+               return 0;
+}
+
+
  int fosa_signal_wait
-                (frsh_signal_t set[], int size, frsh_signal_t *signal_received, 
-                 frsh_signal_info_t *info);
+     (fosa_signal_t set[], int size, fosa_signal_t *signal_received, 
+      fosa_signal_info_t *info)
+{
+  return fosa_signal_timedwait (set, size, signal_received, info, NULL);
+}
+
+
  int fosa_signal_timedwait
-                (frsh_signal_t set[], int size, frsh_signal_t *signal_received, 
-                 frsh_signal_info_t *info, const struct timespec *timeout);
+       (fosa_signal_t set[], int size, fosa_signal_t *signal_received,
+        fosa_signal_info_t *info, const fosa_rel_time_t *timeout)
+{
+       int i, sig;
+       sigset_t wset;
+       siginfo_t nfo;
+
+       if (size < 0) 
+               return EINVAL;
+
+       sigemptyset (&wset);
+       for (i = 0; i < size; i ++) {
+               if (FOSA_SIGNAL_MIN > set [i] || set [i] > FOSA_SIGNAL_MAX)
+                       return EINVAL;
+               sigaddset (&wset, set [i]);
+       }
+       
+       sig = sigtimedwait (&wset, &nfo, timeout);
+       if (sig == -1)
+               return errno;
+       
+       if (info)
+               *info = (fosa_signal_info_t) nfo.si_value.sival_ptr;
+       
+       if (signal_received)
+               *signal_received = sig;
+       
+       return 0;
+}