]> rtime.felk.cvut.cz Git - frescor/fwp.git/commitdiff
CTU FRSh: Added frsh_core, frsh_error files, frsh_aquosa/core.c and synchobj.c
authorMartin <molnar@sum.(none)>
Fri, 5 Sep 2008 17:07:33 +0000 (19:07 +0200)
committerMartin <molnar@sum.(none)>
Fri, 5 Sep 2008 17:07:33 +0000 (19:07 +0200)
frsh/frsh_contract.c
frsh/frsh_core.c [new file with mode: 0644]
frsh/frsh_error.c [new file with mode: 0644]
frsh/frsh_error.h [new file with mode: 0644]
frsh_aquosa/core.c [new file with mode: 0644]
frsh_aquosa/scheduler.c
frsh_aquosa/synchobj.c [new file with mode: 0644]
fwp/lib/fwp_fna.c

index a854b25959a330ce3c3b54b22ea3db0f0601d40e..1d9ba93705c1bcf09840a86465c9085fe7ac9f5e 100644 (file)
@@ -1,10 +1,38 @@
 #include "frsh_contract.h"
 
-int frsh_contract_reserve(frsh_resource_type_t type, void* contract_params, 
-                       frsh_contract_d_t **contractdp )
+typedef unsigned long frsh_vres_handle;
+
+/**
+ * Create contract
+ *
+ */
+frsh_contract_handle frsh_contract_create()
+{
+       /* NOT IMPLEMENTED */
+}
+
+int frsh_contract_reserve(frsh_contract_handle_t contract)
+{
+
+}
+
+int frsh_contract_commit(frsh_contract_handle_t contract)
+{
+
+}
+
+int frsh_contract_cancel(frsh_contract_handle_t contract)
+{
+
+}
+
+frsh_vres_handle frsh_contract_get_vres(frsh_contract_handle_t contract)
+{
+
+}
+
+int frsh_contract_release(frsh_contract_handle_t contract)
 {
-       frsh_resource_t *resource = &frsh_resources[type];
 
-       return resource->contract_ops->reserve(contract_params, contractdp);
 }
 
diff --git a/frsh/frsh_core.c b/frsh/frsh_core.c
new file mode 100644 (file)
index 0000000..1d5015e
--- /dev/null
@@ -0,0 +1,204 @@
+int frsh_init()
+{
+
+
+}
+
+/**
+ * frsh_contract_init()
+ *
+ * The operation receives a pointer to a contract object
+ * and initializes it, setting it to the default values.
+ *
+ * The default values are:
+ *
+ * - resource_id               => 0
+ * - ressource_type            => FRSH_CRT_PROCESSOR
+ * - contract_label               => ""
+ * - budget_min                => {0,0};
+ * - period_max                => {0,0};
+ * - budget_max                => {0,0};
+ * - period_min                => {0,0};
+ * - workload                  => FRSH_WT_INDETERMINATE
+ * - d_equals_t                => true
+ * - contract_type             => FRSH_CT_REGULAR;
+ * - deadline                  => {0,0};
+ * - budget_overrun_signal => 0;  (signal number)
+ * - budget_overrun_siginfo  => {0, NULL};
+ * - deadline_miss_signal  => 0;  (signal number)
+ * - deadline_miss_siginfo   => {0, NULL};
+ *
+ * - granularity               => DEFAULT_GRANULARITY;
+ * - utilization_set;          => size = 0
+ * - quality                   => DEFAULT_QUALITY;    (range 0..100)
+ * - importance                => DEFAULT_IMPORTANCE; (range 1..5)
+ * - preemption_level          => 0; (range 1..2**32-1)
+ * - critical_sections;        => size = 0
+ *
+ * - sched_policy              => DEFAULT_SCHED_POLICY (FRSH_NONE)
+ *
+ * @param     contract the pointer to the contract variable.
+ *
+ * @return 0 if no error \n
+ *     FRSH_ERR_BAD_ARGUMENT :  contract is NULL
+ *
+ **/
+int frsh_contract_init(frsh_contract_t *contract)
+{
+       // alocates contract 
+       cntr = frsh_calloc(FRSH_CONTRACT_SIZE);
+}
+
+/* Functions: frsh_contract_init, 
+ * frsh_contract_set_basic_params, frsh_contract_get_basic_params(), 
+ * frsh_contract_set_resource_and_label(), frsh_contract_get_resource_and_label, 
+ * frsh_contract_set_timing_reqs(), frsh_contract_get_timing_reqs
+ */
+
+///////////////////////////////////////////////////////////////
+//                 CONTRACT NEGOCIATION OPERATIONS
+///////////////////////////////////////////////////////////////
+
+/**
+ * frsh_contract_negotiate()
+ *
+ * The operation negotiates a contract and if accepted it will return
+ * a vres_id.  It will also check that the given contract_label is unique
+ * within the node.
+ *
+ * If the on-line admission test is enabled, it determines whether the
+ * contract can be admitted or not based on the current contracts
+ * established in the system. Then it creates the vres and
+ * recalculates all necessary parameters for the contracts already
+ * present in the system.
+ *
+ * This is a potentially blocking operation, it returns when the
+ * system has either rejected the contract, or admitted it and made it
+ * effective. No thread is bound to the newly created vres, which
+ * will be idle until a thread is bound to it via frsh_thread_bind()
+ * or frsh_thread_create_and_bind().
+ *
+ * This operation can only be executed by threads that are already
+ * bound to an active vres and therefore are being scheduled by the
+ * frsh scheduler.
+ *
+ * @return 0 if successful \n
+ *   FRSH_ERR_CONTRACT_REJECTED:  The contract is not accepted.\n
+ *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
+ *                running \n
+ *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
+ *     main scheduler \n
+ *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not scheduled
+ *     under FRSH scheduler \n
+ *   FRSH_ERR_BAD_ARGUMENT :  if the contract or vres arguments are NULL \n
+ *   FRSH_ERR_TOO_MANY_VRES : if there is no space for more vres
+ *     (the maximum number of them is already reached) \n
+ *   FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS : contract_label is not unique.
+ *
+ **/
+int frsh_contract_negotiate
+        (const frsh_contract_t *contract,
+         frsh_vres_id_t      *vres_id)
+{
+    frsh_in_msg_t   msg;
+    frsh_out_msg_t  reply;
+    size_t          msg_size = 0;
+    size_t          reply_size = 0;
+    int             terror = 0;
+    bool            appscheduled = false;
+
+    memset(&msg, 0, sizeof(msg) );
+    memset(&reply, 0, sizeof(reply) );
+
+    if ( (contract == NULL) || (vres_id == NULL) ) return FRSH_ERR_BAD_ARGUMENT;
+
+    /* Check that the thread is scheduled by FRSH */
+    /**********************************************/
+    PRW(   fosa_ads_get_appscheduled(fosa_thread_self(), &appscheduled)  );
+    if (!appscheduled) {
+        PERROR_AND_RETURN(FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD,
+                    "thread is not an frsh scheduled one");
+    }
+
+    // SWITCH for the type of resource
+    switch (contract->resource_type) {
+        case FRSH_RT_PROCESSOR:
+            // Check that contract label is not in use
+            if (fadt_hash_table_contains_key (&frsh_contract_hashtable,
+                contract->contract_label))
+            {
+                /* The contract cannot be accepted with this name */
+                PERROR_AND_RETURN
+                        ( FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS,
+                          "contract label already exists in this resource");
+            }
+
+            msg_size = msg_type_size + sizeof(frsh_contract_negotiate_in_t);
+            msg.type = FRSH_MT_CONTRACT_NEGOTIATE;
+            msg.val.contract_negotiate.contract = *contract;
+
+            PRW(fosa_ads_invoke_withdata (&msg, msg_size, &reply, &reply_size));
+
+            if (reply_size !=
+                reply_error_size + sizeof(frsh_contract_negotiate_out_t)) {
+                PERROR_AND_RETURN
+                        (FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                         "fosa_ads_invoke_withdata returned wrong data");
+            }
+
+            if (reply.error != 0) {
+                PERROR_AND_RETURN
+                        (reply.error, "the contract negotiation failed");
+            }
+
+            *vres_id = reply.val.contract_negotiate.vres_id;
+
+            // finally, add the label to the hashtable
+
+            if (fadt_hash_table_put (&frsh_contract_hashtable,
+                contract->contract_label,
+                *vres_id) !=0)
+            {
+                /* There is no space in the table (should not happen) */
+                return FRSH_ERR_NO_SPACE;
+            }
+            break;
+        case FRSH_RT_NETWORK:
+        {
+#if FRSH_DISTRIBUTED_MODULE_SUPPORTED
+            // TODO: hash table for labels in rtep network is not ready
+            // TODO: use check_valid_resource_id from distributed.c
+            fna_vres_id_t fna_vres_id;
+            // negotiate the contract through fna callback
+            if (fna_operations[contract->resource_id]->fna_contract_negotiate
+                    (contract->resource_id, contract, &fna_vres_id) != 0) {
+                PERROR_AND_RETURN
+                        (FRSH_ERR_CONTRACT_REJECTED,
+                         "the contract negotiation failed");
+            }
+            // if the contract was accepted create the vres_id
+            frsh_vres_id_set_fields
+                (vres_id, (int) fna_vres_id,
+                 FRSH_RT_NETWORK, contract->resource_id);
+#else
+            PERROR_AND_RETURN (FRSH_ERR_BAD_ARGUMENT, "networks not supported");
+#endif
+        }
+            break;
+           case FRSH_RT_MEMORY:{
+                       int l_err;
+                       l_err = frsh_negotiate_memory_contract(contract, vres_id);
+
+                       if (l_err) PERROR_AND_RETURN (l_err , "Memory negotiation failed");
+
+            /*
+                         PERROR_AND_RETURN (FRSH_ERR_BAD_ARGUMENT, "memory not supported");
+                        */
+               }
+            break;
+
+        default:
+            PERROR_AND_RETURN (FRSH_ERR_BAD_ARGUMENT, "wrong resource_type");
+    }
+    return 0;
+} /* End of frsh_contract_negotiate */
diff --git a/frsh/frsh_error.c b/frsh/frsh_error.c
new file mode 100644 (file)
index 0000000..bdff348
--- /dev/null
@@ -0,0 +1,180 @@
+// -----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2008 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 FRSH (FRescor ScHeduler)
+//
+//  FRSH 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.  FRSH 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 FRSH; see file
+//  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+//  Cambridge, MA 02139, USA.
+//
+//  As a special exception, including FRSH header files in a file,
+//  instantiating FRSH generics or templates, or linking other files
+//  with FRSH 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.
+// -----------------------------------------------------------------------
+//==============================================
+//  ******** *******    ********  **      **
+//  **///// /**////**  **//////  /**     /**
+//  **      /**   /** /**        /**     /**
+//  ******* /*******  /********* /**********
+//  **////  /**///**  ////////** /**//////**
+//  **      /**  //**        /** /**     /**
+//  **      /**   //** ********  /**     /**
+//  //       //     // ////////   //      // 
+//
+// FRSH(FRescor ScHeduler), pronounced "fresh"
+//==============================================
+
+#include <stdio.h>
+#include <string.h>
+
+#include "frsh.h"
+#include "frsh_internal.h"
+
+
+////////////////////////////////////////////////////////////////////////
+//           ERROR REPORTING
+////////////////////////////////////////////////////////////////////////
+
+/* Use to debug an error condition */
+/***********************************/
+int global_error_condition = 0;
+
+
+
+/* These variables get initialised in frsh_init() */
+/**************************************************/
+fosa_abs_time_t frsh_trace_init_timespec;
+long frsh_trace_init_timemsec = -1;
+
+
+//error codes to message section
+static const int frsh_strerror_table_size = FRSH_ERR_LAST_VALUE-FRSH_ERR_BASE_VALUE;
+static char * frsh_strerror_table[] = 
+{
+    "TOO_MANY_TASKS                 ",
+    "BAD_ARGUMENT                   ",
+    "INVALID_SYNCH_OBJ_HANDLE       ",
+    "NO_RENEGOTIATION_REQUESTED     ",
+    "CONTRACT_REJECTED              ",
+    "NOT_SCHEDULED_CALLING_THREAD   ",
+    "NOT_BOUND_THREAD               ",
+    "UNKNOWN_SCHEDULED_THREAD       ",
+    "NOT_CONTRACTED_SERVER          ",
+    "NOT_SCHEDULED_THREAD           ",
+    "TOO_MANY_SERVICE_JOBS          ",
+    "TOO_MANY_SYNCH_OBJS            ",
+    "TOO_MANY_SERVERS_IN_SYNCH_OBJ  ",
+    "TOO_MANY_EVENTS_IN_SYNCH_OBJ   ",
+    "INTERNAL_ERROR                 ",
+    "TOO_MANY_SERVERS               ",
+    "INVALID_SCHEDULER_REPLY        ",
+    "TOO_MANY_PENDING_REPLENISHMENTS",
+    "SYSTEM_ALREADY_INITIALIZED     ",
+    "SHARED_OBJ_ALREADY_INITIALIZED ",
+    "SHARED_OBJ_NOT_INITIALIZED     ",
+    "SCHED_POLICY_NOT_COMPATIBLE    ",
+    "SERVER_WORKLOAD_NOT_COMPATIBLE ",
+    "ALREADY_BOUND                  ",
+    "WRONG_NETWORK                  ",
+    "TOO_LARGE                      ",
+    "BUFFER_FULL                    ",
+    "NO_SPACE                       ",
+    "NO_MESSAGES                    ",
+    "MODULE_NOT_SUPPORTED           ",
+    "SYSTEM_NOT_INITIALIZED         ",
+    "TOO_MANY_SHARED_OBJS           ",
+    "CONTRACT_LABEL_ALREADY_EXISTS  ",
+    "BUDGET_EXPIRED                 ",
+    "SHARED_OBJECT_NOT_PROTECTED    ",
+    "NOT_IMPLEMENTED                ",
+    "CONTRACT_TYPE_NOT_COMPATIBLE   ",
+    "CAPACITY_NOT_DECREASING        ",
+    "CONTRACT_LABEL_UNKNOWN         "
+};
+
+
+
+/**
+ *  frsh_strerror()
+ *
+ *  This function converts an error code to an error message that is
+ *  stored in the buffer starting at the location pointed to by
+ *  message. The size of this buffer is specified by the size
+ *  argument. If the error message is longer than size-1, it is
+ *  truncated to that length. Regardless of whether the message is
+ *  truncated or not, a final zero character that marks the end of the
+ *  string is stored in the buffer.  The function fails if the error
+ *  code passed does not correspond to any of the frsh error codes.
+ *   [@return:
+ *    FRSH_ERR_BAD_ARGUMENT :  error is not a valid value
+ *   ]
+ **/
+int frsh_strerror (int error, char *message, size_t size)
+{
+    char *s;
+//printf("debug: error=%x, LAST=%x, BASE=%x\n", error, FRSH_ERR_LAST_VALUE, FRSH_ERR_BASE_VALUE);
+    if ((error > FRSH_ERR_LAST_VALUE) ||
+        (error <= FRSH_ERR_BASE_VALUE))
+        return FRSH_ERR_BAD_ARGUMENT;
+  
+    s = frsh_strerror_table[error - FRSH_ERR_BASE_VALUE -1];
+    if ( message != NULL && size > 0) {
+        strncpy(message, s, size);
+        message[size-1] = '\0';
+    }
+    return 0;
+}
+
+/* ------------------------------------------------------------------------------------ */
+void my_frsh_strerror(int error, char *sss)
+{
+    char       s[32];
+    frsh_strerror(error, s, 32);
+    printf("(%x ", error);
+    printf(s);
+    printf(") ");
+    printf(sss);
+}
diff --git a/frsh/frsh_error.h b/frsh/frsh_error.h
new file mode 100644 (file)
index 0000000..639a115
--- /dev/null
@@ -0,0 +1,272 @@
+// -----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2008 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 FRSH (FRescor ScHeduler)
+//
+//  FRSH 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.  FRSH 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 FRSH; see file
+//  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+//  Cambridge, MA 02139, USA.
+//
+//  As a special exception, including FRSH header files in a file,
+//  instantiating FRSH generics or templates, or linking other files
+//  with FRSH 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.
+// -----------------------------------------------------------------------
+//frsh_error.h
+//==============================================
+//  ******** *******    ********  **      **
+//  **///// /**////**  **//////  /**     /**
+//  **      /**   /** /**        /**     /**
+//  ******* /*******  /********* /**********
+//  **////  /**///**  ////////** /**//////**
+//  **      /**  //**        /** /**     /**
+//  **      /**   //** ********  /**     /**
+//  //       //     // ////////   //      // 
+//
+// FRSH(FRescor ScHeduler), pronounced "fresh"
+//==============================================
+
+#ifndef        FRSH_ERROR_H_
+#define        FRSH_ERROR_H_
+
+/**
+ * @file frsh_error.h
+ **/
+
+/**
+ * addtogroup core
+ *
+ * @{
+ **/
+
+/* Error codes */
+#define FRSH_NO_ERROR                            0
+
+#define FRSH_ERR_BASE_VALUE                      0x02004000
+
+#define FRSH_ERR_TOO_MANY_TASKS                  0x02004001
+#define FRSH_ERR_BAD_ARGUMENT                    0x02004002
+#define FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE        0x02004003
+#define FRSH_ERR_NO_RENEGOTIATION_REQUESTED      0x02004004
+#define FRSH_ERR_CONTRACT_REJECTED               0x02004005
+#define FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD    0x02004006
+#define FRSH_ERR_NOT_BOUND                       0x02004007
+#define FRSH_ERR_UNKNOWN_SCHEDULED_THREAD        0x02004008
+#define FRSH_ERR_NOT_CONTRACTED_VRES             0x02004009
+#define FRSH_ERR_NOT_SCHEDULED_THREAD            0x0200400A
+#define FRSH_ERR_TOO_MANY_SERVICE_JOBS           0x0200400B
+#define FRSH_ERR_TOO_MANY_SYNCH_OBJS             0x0200400C
+#define FRSH_ERR_TOO_MANY_VRES_IN_SYNCH_OBJ      0x0200400D
+#define FRSH_ERR_TOO_MANY_EVENTS_IN_SYNCH_OBJ    0x0200400E
+#define FRSH_ERR_INTERNAL_ERROR                  0x0200400F
+#define FRSH_ERR_TOO_MANY_VRES                   0x02004010
+#define FRSH_ERR_INVALID_SCHEDULER_REPLY         0x02004011
+#define FRSH_ERR_TOO_MANY_PENDING_REPLENISHMENTS 0x02004012
+#define FRSH_ERR_SYSTEM_ALREADY_INITIALIZED      0x02004013
+#define FRSH_ERR_SHARED_OBJ_ALREADY_INITIALIZED  0x02004014
+#define FRSH_ERR_SHARED_OBJ_NOT_INITIALIZED      0x02004015
+#define FRSH_ERR_SCHED_POLICY_NOT_COMPATIBLE     0x02004016
+#define FRSH_ERR_VRES_WORKLOAD_NOT_COMPATIBLE    0x02004017
+#define FRSH_ERR_ALREADY_BOUND                   0x02004018
+#define FRSH_ERR_RESOURCE_ID_INVALID             0x02004019
+#define FRSH_ERR_TOO_LARGE                       0x0200401A
+#define FRSH_ERR_BUFFER_FULL                     0x0200401B
+#define FRSH_ERR_NO_SPACE                        0x0200401C
+#define FRSH_ERR_NO_MESSAGES                     0x0200401D
+#define FRSH_WRN_MODULE_NOT_SUPPORTED            0x0200401E
+#define FRSH_ERR_NOT_INITIALIZED                 0x0200401F
+#define FRSH_ERR_TOO_MANY_SHARED_OBJS            0x02004020
+#define FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS   0x02004021
+#define FRSH_ERR_BUDGET_EXPIRED                  0x02004022
+#define FRSH_ERR_SHARED_OBJECT_NOT_PROTECTED     0x02004023
+#define FRSH_ERR_NOT_IMPLEMENTED                 0x02004024
+#define FRSH_ERR_CONTRACT_TYPE_NOT_COMPATIBLE    0x02004025
+#define FRSH_ERR_CAPACITY_NOT_DECREASING         0x02004026
+#define FRSH_ERR_CONTRACT_LABEL_UNKNOWN          0x02004027
+#define FRSH_ERR_OUT_OF_BUDGET                          0x02004028
+
+#define FRSH_ERR_LAST_VALUE                      0x02004029
+
+#define ERROR(nn,ss) do {if(nn>FRSH_ERR_BASE_VALUE) my_frsh_strerror(nn, ss); else perror(ss); exit (nn);} while (0)
+
+
+
+
+int frsh_strerror (int error, char *message, size_t size);
+void my_frsh_strerror(int error, char *sss);
+
+
+/**
+ * This str_helper is needed to ensure argument expansion,
+ * see http://www.iar.com/p180591/p180591_eng.php
+ **/
+#define STR_HELPER(x) #x
+
+/**
+ * PERROR_FRESCOR
+ *
+ * This macro checks the given error number and composes a messages accordingly.
+ *
+ * @param nn  Error number
+ * @param ss  Error string (to be appended to FRSH or system error string)
+ **/
+#define PERROR_FRESCOR(_nn_,_ss_) do {         \
+ \
+        char error_string[1024]; \
+ \
+        sprintf(error_string,  "File: %s, in function %s at line %d, error %d: %s\n", __FILE__, __FUNCTION__, __LINE__, (_nn_), _ss_); \
+ \
+               if( (_nn_)>FRSH_ERR_BASE_VALUE ) {      \
+                       my_frsh_strerror( (_nn_), error_string);        \
+               } else {                                \
+                       perror(error_string);                   \
+               }                                       \
+} while(0) 
+
+
+
+/**
+ * PERROR_AND_RETURN
+ *
+ * Macro that displays an error code and message and then returns from
+ * the current function
+ *
+ * @param nn  Error number
+ * @param ss  Error string (to be appended to FRSH or system error string)
+ **/
+#define PERROR_AND_RETURN(nn,ss) do {                  \
+        PERROR_FRESCOR(nn, ss); \
+               return (nn);                            \
+       } while (0)
+
+
+
+
+/**
+ * PERROR_AND_EXIT
+ *
+ * Macro that displays an error code and message and then aborts the
+ * program.
+ *
+ * @param nn  Error number
+ * @param ss  Error string (to be appended to FRSH or system error string)
+ **/
+#define PERROR_AND_EXIT(nn,ss) do {    \
+               PERROR_FRESCOR(nn,ss);          \
+               exit(nn);               \
+       } while (0)
+
+
+/**
+ * PRW:  Perror and Return Wrapper
+ *
+ * Function that calls funccall and checks the result != 0.
+ * In case of error it displays the error code with the function call
+ * as extra error string and returns from the function.
+ *
+ * terror (int) needs to be visible in the point of call.
+ *
+ * @param funccall Code to execute that should return 0 in a non error
+ *                 case. 
+ **/
+#define PRW(funccall)  do { \
+  if ( (terror = funccall ) != 0) \
+  { \
+     PERROR_AND_RETURN( terror, STR_HELPER(funccall) ); \
+  } \
+} while(0)
+
+
+
+/**
+ * PXW:  Perror and eXit Wrapper
+ *
+ * Function that calls funccall and checks the result != 0.
+ * In case of error it displays the error code with the function call
+ * as extra error string and ABORTS the program.
+ *
+ * terror (int) needs to be visible in the point of call.
+ *
+ * @param funccall Code to execute that should return 0 in a non error
+ *                 case. 
+ **/
+#define PXW(funccall)  do { \
+  if ( (terror = funccall ) != 0) \
+  { \
+     PERROR_AND_EXIT( terror, STR_HELPER(funccall) ); \
+  } \
+} while(0)
+
+
+
+/**
+ * PERROR_KERN_AND_EXIT
+ *
+ * Function that displays an error code and message and then aborts the
+ * program.
+ *
+ * @param nn  Error number
+ * @param ss  Error string (to be appended to FRSH or system error string)
+ **/
+#define PERROR_KERN_AND_EXIT(nn, ss) do {              \
+               errno = errno ? errno : (nn);           \
+               kern_printf(ss);                        \
+               exit(nn);                               \
+       } while (0)
+
+#ifdef DEBUG 
+#define FRSH_ERROR(n) do{      \
+               errno = (n);    \
+               PERROR_FRESCOR((n), "");
+       } while (0);
+
+#else 
+#define FRSH_ERROR(n) do{      \
+               errno = (n);    \
+       } while (0);
+#endif
+
+
+/*}*/
+
+#endif             /* !FRSH_ERROR_H_ */
diff --git a/frsh_aquosa/core.c b/frsh_aquosa/core.c
new file mode 100644 (file)
index 0000000..fd660f2
--- /dev/null
@@ -0,0 +1,1558 @@
+// -----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
+//
+//    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
+//
+//           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 FRSH API
+//
+//  FRSH API is free software; you can  redistribute it and/or  modify
+//  it under the terms of  the GNU General Public License as published by
+//  the Free Software Foundation;  either  version 2, or (at  your option)
+//  any later version.
+//
+//  FRSH API  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
+//  distributed  with  FRSH API;  see file COPYING.   If not,  write to the
+//  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
+//  02111-1307, USA.
+//
+//  As a special exception, if you include this header file into source
+//  files to be compiled, this header file does not by itself cause
+//  the resulting executable 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 General
+//  Public License.
+// -----------------------------------------------------------------------
+//==============================================
+//  ******** *******    ********  **      **
+//  **///// /**////**  **//////  /**     /**
+//  **      /**   /** /**        /**     /**
+//  ******* /*******  /********* /**********
+//  **////  /**///**  ////////** /**//////**
+//  **      /**  //**        /** /**     /**
+//  **      /**   //** ********  /**     /**
+//  //       //     // ////////   //      // 
+//
+// FRSH(FRescor ScHeduler), pronounced "fresh"
+//==============================================
+
+/*
+ * frsh_core.c
+ *
+ * This file contains the implementation of FRSH API core functions on top
+ * of the AQuoSA framework, on GNU/Linux platform.
+ *
+ * It's the main file in which all the function are defined but many of them
+ * are implemented via a request to the service thread through a socket
+ * connection.
+ * For the details of the API functions implementation take a look
+ * into the frsh_service_th.c (and related headers) source file.
+ *
+ * The FRSH core API is actually completely implemented and almost all
+ * functions behave as described by the FRSH deliverables and specifications
+ * documents.
+ * There still could be some differences, maily due by the peculiarities of
+ * the AQuoSA framework, and they're briefly discussed in the comments leading
+ * any of the function definition and/or in separate documents
+ *
+ * The most significant issue with the actual implementation is it's limited
+ * to INDETERMINATE contracts, because of the status of the AQuoSA framework
+ * on th 2.6.x Linux platforms.
+ * Support for BOUNDED workload will came as soon as the QoS manager (qmgr) of
+ * AQuoSA will be in place
+ */
+
+/*******************/
+/* I N C L U D E S */
+/*******************/
+
+/* Linux files */
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#define __USE_UNIX98
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+/* FRSH files */
+#include "fosa.h"
+#include "frsh.h"
+#include "frsh_service_th.h"
+
+/* AQuoSA files */
+#include <aquosa/qres_lib.h>
+#include <aquosa/qsup_lib.h>
+
+/* local timepsec <-> usec utility macros */
+#include "frsh_time_extras.h"
+
+/***********************************/
+/* G L O B A L   V A R I A B L E S */
+/***********************************/
+
+int frsh_initialized = 0;              /* framework initialization flag */
+//#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_SAFETY_CHECK
+pid_t frsh_service_th_pid;             /* service thread pid cache */
+//#endif
+
+
+/*********************************************************/
+/* U T I L I T Y   F U N C T I O N   A N D   M A C R O S */
+/*********************************************************/
+
+
+/****************************************/
+/*     CORE API IMPLEMENTATION         */
+/****************************************/
+
+/////////////////////////////////////////////////
+// I N I T I A L I Z A T I O N   S E R V I C E S
+/////////////////////////////////////////////////
+
+/*
+ * frsh_init(), initialize FRSH for the calling process
+ *
+ * Must be called before starting using the framework.
+ * No FRSH call will be successful if this routine is not invoked
+ *
+ * Note that no BACKGROUND is created and negotiated and the caller thread
+ * is bound to no BACKGROUND vres, since no way is provided in order of
+ * specifying the contract label and get back the vres id!
+ *
+ * Note also that, since in this implementation the threads/processes with
+ * backgound contracts are left into the default Linux scheduler hands' and
+ * not attached to any AQuoSA server, while we're violating what D-AC2v1
+ * (pag. 14) says, we achieve exactly the same behaviour!!
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_ALREADY_INITIALIZED
+ *  FRSH_ERR_INTERNAL_ERROR (something, different from the previous case, gone wrong)
+ */
+
+/* forward declarations, see below ... */
+static void frsh_scheduler_signal_handler(int signum, siginfo_t *siginfo, void *cntx);
+
+static void frsh_qres_cleanup_wrapper();
+
+int frsh_aquosa_init()
+{
+       struct sigaction frsh_scheduler_signal_action;
+
+       /* check FRSH is not already initialized */
+       if (frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_SYSTEM_ALREADY_INITIALIZED,
+                               "can't initialize the systema again (frsh_init already called)");
+       /* check if the name service is available and ty to start it if not */
+       if (frsh_service_th_init(&frsh_service_th_pid) != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't find nor start the FRSH service thread");
+       /* (try to) initialize the AQuoSA Framework */
+       if (qres_init() != QOS_OK || qsup_init() != QOS_OK)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't initialize AQuoSA framework");
+       /* setup the default scheduler signal handling behaviour */
+       frsh_scheduler_signal_action.sa_sigaction = frsh_scheduler_signal_handler;
+       pthread_sigmask(0, NULL, &frsh_scheduler_signal_action.sa_mask);
+       sigaddset(&frsh_scheduler_signal_action.sa_mask, FRSH_SCHEDULER_SIGNAL);        /* blocked by default */
+       pthread_sigmask(SIG_SETMASK, &frsh_scheduler_signal_action.sa_mask, NULL);
+       frsh_scheduler_signal_action.sa_flags = SA_SIGINFO | SA_RESTART;
+       if (sigaction(FRSH_SCHEDULER_SIGNAL, &frsh_scheduler_signal_action, NULL) < 0)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                       "can't setup the signal handler for thread creation");
+
+       /* install the cleanup function of th AQuoSA framework as an exit
+        * handler function (quite futile but, for now, it's sufficent) */
+       if (atexit(frsh_qres_cleanup_wrapper))
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't install AQuoSA cleanup handler");
+       /* initialize the synchronization object repository */
+       if (!synchobj_repo_init())
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't initialize the synchronization objects");
+       /* FRSH in now initialized so that any subsequent
+        * call to this function within the same process will fail */
+       frsh_initialized = 1;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * default signal handler for the FRSH_SCHEDULER_SIGNAL
+ *
+ * As default behaviour this function is installed as signal handler (with
+ * sa_sigaction field in the stucture) and the signal is blocked.
+ *
+ * The handler does nothing for now, but may be useful in future
+ */
+static void frsh_scheduler_signal_handler(int signum, siginfo_t *siginfo, void *cntx) {
+       if (signum != FRSH_SCHEDULER_SIGNAL)
+               PERROR_AND_EXIT(FRSH_ERR_INTERNAL_ERROR,
+                               "wrong signal received while witing for FRSH_SCHEDULER_SIGNAL");
+}
+
+/*
+ * installed as an exit handler (with 'atexit()') by the initialization
+ * code... For now it only calls the cleanup function of the AQuoSA
+ * Framework
+ */
+static void frsh_qres_cleanup_wrapper() {
+       if (qres_cleanup() != QOS_OK)
+               PERROR_FRESCOR(FRSH_ERR_INTERNAL_ERROR,
+                       "WARNING: error during clenup of AQuoSA framework");
+}
+
+/*
+ * frsh_thread_bind(), create a new thread and bind it to a vres
+ * frsh_thread_create_in_background(), create a new thread and a new BACKGROUND contract and bind them
+ *
+ * The two functions both create a new thread and bind it to a vres, existing
+ * fr the former, created for the latter.
+ *
+ * The implementation uses a wrapper function as the new thread code (it's
+ * the simplest way to handle some issues on POSIX 'pthread_t' and
+ * 'pthread_self()', for a detailed explanation of the "problem" ask the
+ * authors via e-mail) which, on its turn, bind itself to the vres and then
+ * run the user provided code. The API calls simply create the new thread,
+ * using the wrapper thread code, and return.
+ *
+ * Note that in order to return the caller the descriptor of the new created
+ * thread (known to the wrapped thread but not entirely to the API calls) a
+ * special 'struct' data type is passed as the parameter of the wrapper thread
+ * and a simple sinchronization mechanism based on signals is realized.
+ * Also the some of the return values are handled this way (using signals)
+ *
+ * possible return values:
+ *  see below the comments of each specific API call
+ */
+
+/*
+ * structure used to pass the new created thread (or better its wrapper) the
+ * arguments it needs to bind itself to the vres.
+ *
+ * Note it also include (in 'pthread_code' and in 'pthread_arg') effective
+ * thread code and argument provided by the user to the original API
+ * 'frsh_thread_create_and_bind()' call
+ */
+typedef struct {
+       frsh_thread_id_t parent_thread_id;
+       frsh_thread_id_t *thread_id;
+       //pthread_t *pthread_pthread_id;
+       //pid_t *pthread_linux_pid;
+       //tid_t *pthread_linux_tid;
+       frsh_vres_id_t vres;
+       frsh_thread_code_t pthread_code;
+       void *pthread_arg;
+} wrapper_pthread_arg_t;
+
+/* forward declaration of the wrapper function */
+static void *wrapper_pthread_create(void *warg);
+
+/*
+ * API call for 'frsh_thread_create_and_bind()', as said prepares the
+ * wrapper code argument data structure, create the new thread and wait
+ * its acknowledgment before stepping over
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
+ *  whatever 'fosa_thread_create()' returns
+ *  FRSH_ERR_INTERNAL_ERROR (something wrong in signal handling)
+ */
+int frsh_thread_create_and_bind(const frsh_vres_id_t vres,
+       frsh_thread_id_t *thread,
+       frsh_thread_attr_t *attr,
+       frsh_thread_code_t thread_code,
+       void *arg)
+{
+       wrapper_pthread_arg_t wp;
+       int thread_status;
+       //sigset_t thread_wait_mask;
+       frsh_signal_t wait_signal;
+       frsh_signal_info_t wait_signal_info;
+       struct timespec wait_signal_timeout;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if ((thread == NULL) || (thread_code == NULL))
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't create a thread with NULL thread_core or return it in a NULL thread");
+       /* 
+        * setup the wrapper code and args for the new
+        * created thread to fill in
+        *
+        * Remember:
+        *  frsh_thread_id_t => struct {
+        *                       pthread_t pthread_id;
+        *                       pid_t linux_pid;
+        *                       tid_t linux_tid;
+        *                      };
+        */
+       wp.parent_thread_id = fosa_thread_self();
+       wp.thread_id = thread;  /* directly fill the user provided thread descriptor pointer */
+       //wp.pthread_pthread_id = &(thread->pthread_id);
+       //wp.pthread_linux_pid = &(thread->linux_pid);
+       //wp.pthread_linux_tid = &(thread->linux_tid);
+       wp.vres = vres;
+       wp.pthread_code = thread_code;
+       wp.pthread_arg = arg;
+       /* create the wrapper thread */
+       thread_status = fosa_thread_create(NULL, attr, wrapper_pthread_create,(void*) &wp);
+       if (thread_status != 0)
+               PERROR_AND_RETURN(thread_status,
+                               "can't create the new thread");
+       /* prepare a suited signal mask and wait for the new
+        * thread to acknowledge us it has filled the pointers with the descriptor*/
+       //pthread_sigmask(0, NULL, &thread_wait_mask);
+       //sigdelset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
+       wait_signal = FRSH_SCHEDULER_SIGNAL;
+       fosa_set_accepted_signals(&wait_signal, 1);
+       wait_signal_timeout.tv_sec = 0;
+       wait_signal_timeout.tv_nsec = 500000000;        /* half a second timeout!! */
+       //if (sigsuspend(&thread_wait_mask) != -1)
+       if (fosa_signal_timedwait(&wait_signal, 1, NULL, &wait_signal_info, &wait_signal_timeout) < 0)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't synchronize with the new created thread");
+       if (wait_signal_info.sival_int != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(wait_signal_info.sival_int,
+                               "can't create and bind the new thread");
+       /* restore the signal mask to its original */
+       //sigaddset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
+       //pthread_sigmask(FRSH_SCHEDULER_SIGNAL, &thread_wait_mask, NULL);
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * API call for 'frsh_thread_create_in_background()', as said creates a
+ * background contract and negotiate it (we know they're always accepted
+ * but we need to get the service thread account fo the new vres), then
+ * create the new thread, exactly as seen in 'frsh_thread_create_and_bind()'
+ * and wait for its acknowledgment
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL thread_id, thread_code, contract_label or vres_id)
+ *  FRSH_ERR_TOO_MANY_VRES(*)
+ *  FRSH_ERR_CONTRACT_ID_ALREADY_EXISTS(*)
+ *  FRSH_ERR_CONTRACT_REJECTED(*)
+ *  whatever 'fosa_thread_create()' returns
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INTERNAL_ERROR (something wrong in signal handling)
+ */
+int frsh_thread_create_in_background(frsh_thread_code_t thread_code,
+       const void *thread_arg,
+       const frsh_contract_label_t contract_label,
+       frsh_thread_attr_t *attr,
+       frsh_thread_id_t *thread_id,
+       frsh_vres_id_t *vres_id)
+{
+       frsh_contract_t contract;
+       frsh_in_msg_t contract_msg;
+       frsh_out_msg_t vres_msg;
+
+       wrapper_pthread_arg_t wp;
+       int thread_status;
+       //sigset_t thread_wait_mask;
+       frsh_signal_t wait_signal;
+       frsh_signal_info_t wait_signal_info;
+       frsh_rel_time_t wait_signal_timeout;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if ((thread_code == NULL) || (thread_id == NULL))
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't create a thread with NULL thread_code or return it in a NULL thread_id");
+       if (contract_label == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't give the contract a NULL contract_label");
+       if (vres_id == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't negotiate for a NULL vres_id");
+
+       /* initialize a contract core parameters
+        * exactly as if we've called 'frsh_contract_init()' */
+       /* Core contract attributes setup */
+       contract.resource_id = FRSH_RESOURCE_ID_DEFAULT;
+       contract.resource_type = FRSH_RT_PROCESSOR;
+       /* contract.contract_label not modified/initialized */
+       contract.budget_min = FOSA_USEC_TO_REL_TIME(0);
+       contract.period_max = FOSA_USEC_TO_REL_TIME(0);
+       contract.workload = FRSH_WT_INDETERMINATE;
+       contract.contract_type = FRSH_CT_REGULAR;
+       contract.d_equals_t = true;
+       contract.deadline = FOSA_USEC_TO_REL_TIME(0);
+       contract.budget_overrun_signal = FRSH_NULL_SIGNAL;
+       contract.budget_overrun_siginfo.sival_int = 0;
+       contract.deadline_miss_signal = FRSH_NULL_SIGNAL;
+       contract.deadline_miss_siginfo.sival_int = 0;
+       /* setup id parameters of the contract
+        * as if we've called 'frsh_contract_set_resource_and_label()' */
+       contract.resource_type = FRSH_RT_PROCESSOR;
+       contract.resource_id = FRSH_RESOURCE_ID_DEFAULT;
+       strncpy(contract.contract_label, contract_label, FRSH_CONTRACT_LABEL_MAXLENGTH);
+       /* setup basic contract parameters
+        * (in order to specify it's a background contract!)
+        * as if we've called 'frsh_contract_set_basic_params()' */
+       contract.workload = FRSH_WT_INDETERMINATE;
+       contract.contract_type = FRSH_CT_BACKGROUND;
+       /* setup additional timing parameters for the contract
+        * as if we've called 'frsh_contract_set_timing_reqs()' */
+       contract.d_equals_t = true;
+       /* ask the service thread for the contract negotiation
+        * (as if we've called 'frsh_contract_negotiate()') */
+       /* prepare the message */
+       contract_msg.type = FRSH_MT_NEGOTIATE_CONTRACT;
+       contract_msg.val.negotiate_contract.contract = contract;
+       /* contact the service thread for contract negotiation */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &contract_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (vres_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(vres_msg.error,
+                               "can't negotiate the new background contract");
+       *vres_id = vres_msg.val.negotiate_contract.vres_id;
+       /* create a new thread with the described wrapper
+        * as thread code in order to handle the binding to the
+        * just created background vres (and to signal us when it's done!)*/
+       wp.parent_thread_id = fosa_thread_self();
+       wp.thread_id = thread_id;       /* directly fill the user provided thread descriptor pointer */
+       //wp.pthread_pthread_id = &(thread_id->pthread_id);
+       //wp.pthread_linux_pid = &(thread_id->linux_pid);
+       //wp.pthread_linux_tid = &(thread_id->linux_tid);
+       wp.vres = *vres_id;
+       wp.pthread_code = thread_code;
+       wp.pthread_arg = (void*) thread_arg;
+       /* create the wrapper thread */
+       thread_status = fosa_thread_create(NULL, attr, wrapper_pthread_create,(void*) &wp);
+       if (thread_status != 0)
+               PERROR_AND_RETURN(thread_status,
+                       "can't create the new background thread");
+       /* prepare a suited signal mask and wait for the new
+        * thread to acknowledge us it has filled the pointers with the descriptor*/
+       //pthread_sigmask(0, NULL, &thread_wait_mask);
+       //sigdelset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
+       wait_signal = FRSH_SCHEDULER_SIGNAL;
+       fosa_set_accepted_signals(&wait_signal, 1);
+       /* half a second timeout!! */
+       wait_signal_timeout = FOSA_USEC_TO_REL_TIME(500000);
+       //if (sigsuspend(&thread_wait_mask) != -1)
+       if (fosa_signal_timedwait(&wait_signal, 1, NULL, &wait_signal_info, &wait_signal_timeout) < 0)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't synchronize with the new created background thread");
+       if (wait_signal_info.sival_int != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(wait_signal_info.sival_int,
+                               "can't create and bind the new background thread");
+       /* restore the signal mask to its original */
+       //sigaddset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
+       //pthread_sigmask(FRSH_SCHEDULER_SIGNAL, &thread_wait_mask, NULL);
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * code for the described wrapper, it only asks the service thread the
+ * binding of itself to the vres and the directly run the user provided
+ * thread code.
+ *
+ * Note that some of the return values of the API
+ * 'frsh_thread_create_and_bind()' or 'frsh_thread_create_in_background()'
+ * call are also possible exit status of the new thread
+ *
+ * possible exit status:
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ *  FRSH_ERR_INTENRAL_ERROR (something wrong with threads and signal handling)
+ *  FRSH_ERR_TOO_MANY_TASKS(*)
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  whatever the user provided code 'pthread_code' returns
+ */
+static void* wrapper_pthread_create(void *warg)
+{
+       frsh_in_msg_t bind_msg;
+       frsh_out_msg_t vres_msg;
+       frsh_signal_info_t frsh_status_siginfo;
+
+       /* fill both local and on the calling thread descriptor */
+       wrapper_pthread_arg_t pth = *((wrapper_pthread_arg_t*) warg);
+       *(pth.thread_id) = fosa_thread_self();
+       //*(pth.pthread_pthread_id) = this_thread.pthread_id;
+       //*(pth.pthread_linux_pid) = this_thread.linux_pid;
+       //*(pth.pthread_linux_tid) = this_thread.linux_tid;
+       /* prepare the message */
+       bind_msg.type = FRSH_MT_BIND_THREAD;
+       bind_msg.val.bind_thread.thread_id = *(pth.thread_id);
+       bind_msg.val.bind_thread.vres_id = pth.vres;
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &bind_msg,&vres_msg) != FRSH_SERVICE_TH_NO_ERROR) {
+                       PERROR_FRESCOR(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                                       "can't receive correct answer from the service thread");
+                       pthread_exit((void*) FRSH_ERR_INVALID_SCHEDULER_REPLY); // move to fosa_???
+       }
+       if (vres_msg.error != FRSH_NO_ERROR) {
+               PERROR_FRESCOR(vres_msg.error, "can't bind to the vres");
+               pthread_exit((void*) vres_msg.error);                           // move to fosa_???
+       }
+       /* signal our 'creator' we've filled the pointers
+        * it needs and we've (at least tried to) bound ourself */
+       frsh_status_siginfo.sival_int = vres_msg.error;
+       if (fosa_signal_queue(FRSH_SCHEDULER_SIGNAL, frsh_status_siginfo, pth.parent_thread_id) < 0) {
+               PERROR_FRESCOR(FRSH_ERR_INTERNAL_ERROR,
+                       "can't acknowledge the new thread creation");
+               pthread_exit((void*) FRSH_ERR_INTERNAL_ERROR);                  // move to fosa_???
+       }
+
+       return pth.pthread_code(pth.pthread_arg);
+}
+
+/*
+ * frsh_thread_bind(), bind a thread to a vres
+ *
+ * Asks the service thread for binding of a thread to a valid, REGULAR and
+ * contracetd vres.
+ * If all is ok the thread is attached to an AQuoSA resource reservation server
+ *
+ * As usual the code below simply prepares a message, send it and wait for
+ * the answer from the service thread, for details on the implementation check
+ * 'bind_thread()' in the frsh_service_th.c source file
+
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_BAD_ARGUMENT(*) (invalid or dummy vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_ALREADY_BOUND(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_thread_bind(const frsh_vres_id_t vres, const frsh_thread_id_t thread)
+{
+       frsh_in_msg_t bind_msg;
+       frsh_out_msg_t vres_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       /* prepare the message */
+       bind_msg.type = FRSH_MT_BIND_THREAD;
+       bind_msg.val.bind_thread.thread_id = thread;
+       bind_msg.val.bind_thread.vres_id = vres;
+       /* contact the service thread for bind the thread */
+       if (frsh_service_th_ask_for(frsh_service_th_pid,&bind_msg,&vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (vres_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(vres_msg.error,
+                               "can't bind the thread");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_thread_unbind(), unbind a thread from a vres
+ *
+ * Asks the service thread for revoke the binding of a thread to a its actual
+ * vres.
+ * If all is ok the thread is detached from the AQuoSA resource
+ * reservation server.
+ *
+ * The code below only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'unbind_thread()' in the
+ * frsh_service_th.c source file
+
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_BAD_ARGUMENT(*) (invalid thread)
+ *  FRSH_ERR_NOT_BOUND(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_thread_unbind(const frsh_thread_id_t thread)
+{
+       frsh_in_msg_t unbind_msg;
+       frsh_out_msg_t reply_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       /* prepare the message */
+       unbind_msg.type = FRSH_MT_UNBIND_THREAD;
+       unbind_msg.val.unbind_thread.thread_id = thread;
+       /* contact the service thread for unbind the thread */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &unbind_msg, &reply_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (reply_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(reply_msg.error,
+                               "can't unbind the thread");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_thread_get_vres_id(), get the id vres of a vres bound to a thread
+ *
+ * Asks the service thread for the id of a particular vres, knowing the thread
+ * bound to it.
+ *
+ * The code below only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_thread_vres_id()' in the
+ * frsh_service_th.c source file
+
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_BAD_ARGUMENT(*) (invalid thread or NULL vres)
+ *  FRSH_ERR_NOT_BOUND(*) (-IMPOSSIBLE- thread not bound)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_thread_get_vres_id(const frsh_thread_id_t thread,
+       frsh_vres_id_t *vres_id)
+{
+       frsh_in_msg_t thread_msg;
+       frsh_out_msg_t vres_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (vres_id == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return the id in a NULL vres_id");
+       /* prepare the message */
+       thread_msg.type = FRSH_MT_GET_THREAD_VRES_ID;
+       thread_msg.val.get_thread_vres_id.thread_id = thread;
+       /* contact the service thread for the vres id */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &thread_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (vres_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(vres_msg.error,
+                               "can't get the vres id");
+       /* store the vres id only now so, if something
+        * goes wrong, the vres_id pointer is returned untouched */
+       *vres_id = vres_msg.val.get_thread_vres_id.vres_id;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_thread_self(), get the thread and vres id of the caller
+ *
+ * Simply returns the thread id of the caller and the vres id to which
+ * (if any) it's bound.
+ *
+ * Note that the thread id is always returned, while the retrieval of the vres
+ * id can be skipped passing a NULL pointer as vres_self argument.
+ *
+ * Nota also that the thread id could be retieved via a simple FOSA call, while
+ * for the vres id we can only ask it to the service thread.
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL thread_self)
+ *  all that 'frsh_thread_get_vres_id()' returns (FRSH_ERR_NOT_BOUND)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+//int frsh_thread_self(frsh_thread_id_t *thread_self, frsh_vres_id_t *vres_self)
+//{
+//     frsh_in_msg_t thread_msg;
+//     frsh_out_msg_t vres_msg;
+//
+//     /* check for framework initialization and arguments */
+//     if (!frsh_initialized)
+//             PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+//                             "can't proceed before initializing FRSH with 'frsh_init()'!");
+//     if (thread_self == NULL)
+//             PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+//                             "can't put self thread id in a NULL thread_self");
+//     /* get the thread id of ourself */
+//     *thread_self = fosa_thread_self();
+//     /* get, if requested, even the vres id of ourself */
+//     if (vres_self != NULL) {                
+//             /* prepare the message */
+//             thread_msg.type = FRSH_MT_GET_THREAD_VRES_ID;
+//             thread_msg.val.get_thread_vres_id.thread_id = *thread_self;
+//             /* contact the service thread for the vres id */
+//             if (frsh_service_th_ask_for(frsh_service_th_pid, &thread_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+//                     PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+//                             "can't receive correct answer from the service thread");
+//             if (vres_msg.error != FRSH_NO_ERROR)
+//                     /* possible return values are listed in the description
+//                      * of the function upward (the one marked with '(*)') */
+//                     PERROR_AND_RETURN(vres_msg.error,
+//                                     "can't get the vres id of the calling thread");
+//             /* vres_self pointer untouched if not all gone well */
+//             *vres_self = vres_msg.val.get_thread_vres_id.vres_id;
+//     }
+//
+//     return FRSH_NO_ERROR;
+//}
+
+/*
+ * frsh_vres_get_contract(), get the contract associated to a vres
+ *
+ * Simply returns contract associated to a valid (and contracted!) vres.
+ *
+ * As usual only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_contract()' in the
+ * frsh_service_th.c source file
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL contract)
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_vres_get_contract(const frsh_vres_id_t vres, frsh_contract_t *contract)
+{
+       frsh_in_msg_t vres_msg;
+       frsh_out_msg_t contract_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (contract == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return contract parameters in a NULL contract");
+       /* prepare the message */
+       vres_msg.type = FRSH_MT_GET_CONTRACT;
+       vres_msg.val.get_contract.vres_id = vres;
+       /* contact the service thread for the contract */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &vres_msg, &contract_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (contract_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(contract_msg.error,
+                               "can't get the contract");
+       /* contract pointer untouched if something has gone wrong */
+       *contract = contract_msg.val.get_contract.contract;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_resource_get_vres_from_label(), get a contracted vres id from the label of the contract
+ *
+ * Returns the id of a contracted vres using as a search key the label of
+ * the contract, provided it's valid!
+ *
+ * As usual only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_label_vres_id()' in the
+ * frsh_service_th.c source file
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL vres or contract label)
+ *  FRSH_ERR_BAD_ARGUMENT(*) (unknown contract label)
+ *  //FRSH_ERR_CONTRACT_LABEL_UNKNOWN(*) (unknown contract label)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ *  FRSH_ERR_NOT_IMPLEMENTED
+ */
+int frsh_resource_get_vres_from_label(const frsh_contract_label_t contract_label,
+       const frsh_resource_type_t resource_type,
+       const frsh_resource_id_t resource_id,
+       frsh_vres_id_t *vres)
+{
+       frsh_in_msg_t label_msg;
+       frsh_out_msg_t vres_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (contract_label == NULL || vres == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't search for a NULL contract_label or return id in a NULL vres");
+       /* this implementation is limited to processor type of resources */
+       if (resource_type != FRSH_RT_PROCESSOR ||
+               resource_id != FRSH_RESOURCE_ID_DEFAULT)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_IMPLEMENTED,
+                               "can't handle resource types different from PROCESSOR with DEFAULT id ones");
+       /* prepare the message */
+       label_msg.type = FRSH_MT_GET_LABEL_VRES_ID;
+       strncpy(label_msg.val.get_label_vres_id.contract_label, contract_label, FRSH_CONTRACT_LABEL_MAXLENGTH);
+       /* contact the service thread for the vres */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &label_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (vres_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(vres_msg.error,
+                               "can't get the vres");
+       /* vres pointer untouched if something has gone wrong */
+       *vres = vres_msg.val.get_label_vres_id.vres_id;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_contract_cancel(), remove a contract and destroy the vres
+ *
+ * Asks the service thread for the elimination of a previously negotiated
+ * contract and the destruction of the associated vres, causing all the
+ * bounded thread to unbind themself from it.
+ *
+ * The code below simply prepares the message for the service thread, then
+ * send it and wait untill a response is received. For detailed
+ * implementation analysis check the function 'cancel_contract()' in the
+ * frsh_service_th.c source file
+ *
+ * Note that in this implementation if a vres is destroyed and all bounded
+ * thread are unbound they don't automatically stop their execution (as
+ * the FRSH docs seems to suggest), they simply get re-attached to the
+ * standard Linux scheduler and start running outside from the AQuoSA
+ * framework and with no more guarantees.
+ *
+ * Note also that if this call fails we can not guess if the vres has
+ * effectively been destroyed, if the thread have been unbound, ecc. and
+ * it's usually not safe (as in all other cases?!?!) to continue running
+ * the program making some kind of (surely wrong!!) assumption
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_contract_cancel(const frsh_vres_id_t vres)
+{
+       frsh_in_msg_t vres_msg;
+       frsh_out_msg_t reply_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       /* prepare the message */
+       vres_msg.type = FRSH_MT_CANCEL_CONTRACT;
+       vres_msg.val.cancel_contract.vres_id = vres;
+       /* contact the service thread for the contract cancellation */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &vres_msg, &reply_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (reply_msg.error != FRSH_NO_ERROR)
+               /* possible return values are listed in the description
+                * of the function upward (the one marked with '(*)') */
+               PERROR_AND_RETURN(reply_msg.error,
+                               "can't cancel the contract");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_contract_renegotiate_sync(), try to change the parameters of a contract
+ *
+ * Tries to change the parameters of a contract requesting a new negotiation
+ * and waits until the request is satisfied or refused.
+ * As requested by the API specs the old contract parameters remain valid if
+ * the renegotiation fails (which actually won't never happen!! See below)
+ *
+ * All parameters of a contract can be changed, included it's label, but,
+ * since we can't create (and return the id to the caller) a new vres,
+ * it's forbidden to change the contract type.
+ * So REGULAR contract can't become DUMMY or BACKGROUND but must stay REGULAR
+ * (an so on with the other types)
+ *
+ * Note also that, actually, there are some "little" issues with the AQuoSA
+ * implementation of the "parameter changing" of servers and, since this is
+ * only the simple code that handle request/response to/from the service
+ * thread, you've got to check the comments and the code of
+ * 'renegotiate_contract()' in the frsh_service_th.c source file for more
+ * details
+ * 
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL new_contract)
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres or trying to change the contract type)
+ *  FRSH_ERR_CONTRACT_ID_ALREADY_EXISTS(*) (new contract label already exists)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_CONTRACT_REJECTED(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_contract_renegotiate_sync(const frsh_contract_t *new_contract,
+       const frsh_vres_id_t vres)
+{
+       frsh_in_msg_t contract_msg;
+       frsh_out_msg_t reply_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (new_contract == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't renegotiate to a NULL new_contract");
+       /* actual limits of this implementation */
+       if (!new_contract->d_equals_t ||
+               new_contract->workload != FRSH_WT_INDETERMINATE)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_IMPLEMENTED,
+                               "can't setup deadline different from period within this implementation");
+       /* prepare the message */
+       contract_msg.type = FRSH_MT_RENEGOTIATE_CONTRACT;
+       contract_msg.val.renegotiate_contract.new_contract = *new_contract;
+       contract_msg.val.renegotiate_contract.vres_id = vres;
+       /* contact the service thread for the contract renegotiation */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &contract_msg, &reply_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (reply_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(reply_msg.error,
+                               "can't renegotiate the contract");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_contract_renegotiate_async(), try to change the parameters of a contract but don't wait the exitus
+ *
+ * Exactly equal to previous function ('frsh_contract_renegotiate_sync()')
+ * tries to change the parameters of a contracted vres via the negotiation of
+ * a new contract for it.
+ *
+ * The only difference is here we don't wait for the service thread to handle
+ * our request and answer, we simply step forward, eventually asking for a
+ * signal to be delivered (if the service thread is running on the same
+ * machine of us!) at job completion.
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_contract_renegotiate_async(const frsh_contract_t *new_contract,
+       const frsh_vres_id_t vres,
+       const frsh_signal_t signal_to_notify,
+       const frsh_signal_info_t signal_info)
+
+{
+       frsh_in_msg_t contract_msg;
+       frsh_out_msg_t reply_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (new_contract == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't request a renegotiation to a NULL new_contract");
+       /* actual limits of this implementation */
+       if (!new_contract->d_equals_t ||
+               new_contract->workload != FRSH_WT_INDETERMINATE)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_IMPLEMENTED,
+                               "can't setup deadline different from period within this implementation");
+       /* prepare the message */
+       contract_msg.type = FRSH_MT_REQUEST_CONTRACT_RENEGOTIATION;
+       contract_msg.val.request_contract_renegotiation.new_contract = *new_contract;
+       contract_msg.val.request_contract_renegotiation.vres_id = vres;
+#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
+       contract_msg.val.request_contract_renegotiation.signal = signal_to_notify;
+       contract_msg.val.request_contract_renegotiation.siginfo = signal_info;
+       contract_msg.val.request_contract_renegotiation.thread_to_signal = fosa_thread_self();
+#endif
+       /* contact the service thread for the contract renegotiation */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &contract_msg, &reply_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               /* the reply mesage has no sense here since the
+                * service thread does not process our request synchronously */
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_vres_get_renegotiation_status(), obtain the status of the last renegotiation operation
+ *
+ * Simply returns the actual renegotiation status of a vres, as reported
+ * by the service thread.
+ *
+ * As usual only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_renegotiation_status()'
+ * in the frsh_service_th.c source file
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL renegotiation_status)
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_vres_get_renegotiation_status (const frsh_vres_id_t vres,
+       frsh_renegotiation_status_t *renegotiation_status)
+{
+       frsh_in_msg_t vres_msg;
+       frsh_out_msg_t status_msg;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (renegotiation_status == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return status in a NULL renegotiation_status");
+       /* prepare the message */
+       vres_msg.type = FRSH_MT_GET_RENEGOTIATION_STATUS;
+       vres_msg.val.get_renegotiation_status.vres_id = vres;
+       /* contact the service thread for the contract renegotiation */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &vres_msg, &status_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (status_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(status_msg.error,
+                               "can't get the renegotiation status");
+       /* renegotiation_stratus pointer untouched if something has gone wrong */
+       *renegotiation_status = status_msg.val.get_renegotiation_status.renegotiation_status;
+
+       return FRSH_NO_ERROR;
+}
+
+/////////////////////////////////////////////////////////////
+// G R O U P   O F   C O N T R A C T S   O P E R A T I O N S
+/////////////////////////////////////////////////////////////
+
+int contracts_up_status[FRSH_MAX_N_VRES];      // should be one of the functions output parameter for this implementation
+int vres_touch_status[FRSH_MAX_N_VRES];                // should be one of the functions output parameter for this implementation
+int vres_down_status[FRSH_MAX_N_VRES];         // should be one of the functions output parameter for this implementarion
+
+/* 
+ * frsh_group_negotiate()
+ *
+ * ...
+ */
+int frsh_group_negotiate (const frsh_contracts_group_t *contracts_up,
+       const frsh_vres_group_t *vres_down,
+       frsh_vres_group_t *vres_up)
+{
+       frsh_in_msg_t contract_msg;
+       frsh_out_msg_t vres_msg;
+       int i;
+
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                       "place a call frsh_init first!");
+       if (contracts_up == NULL && vres_down == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                       "could not negotiate/cancel a NULL contract or vres group");
+       if (vres_up == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                       "can't negotiate for a NULL vres group");
+       /* contact the service thread for contract negotiation */
+       contract_msg.type = FRSH_MT_NEGOTIATE_GROUP;
+       if (contracts_up != NULL)
+               for (i = 0; i < contracts_up->size; i++) {
+                       if (contracts_up->contracts[i] == NULL)
+                               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                                       "could not negotiate a NULL contract in the group");
+                       if (!contracts_up->contracts[i]->d_equals_t)            // limited by by this implementation
+                               PERROR_AND_RETURN(FRSH_ERR_NOT_IMPLEMENTED,
+                                       "only deadline=period implemented!");
+                       contract_msg.val.negotiate_group.contracts_up[i] = *(contracts_up->contracts[i]);
+               }
+       contract_msg.val.negotiate_group.contracts_up_number = contracts_up->size;
+       if (vres_down != NULL)
+               for (i = 0; i < vres_down->size; i++)
+                       contract_msg.val.negotiate_group.vres_down[i] = vres_down->vres[i];
+       contract_msg.val.negotiate_group.vres_down_number = vres_down->size;
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &contract_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,     // it's _service_ thread, not scheduler !!
+                       "service thread not/wrong responding");
+       for (i = 0; i < contracts_up->size; i++) {
+               contracts_up_status[i] = vres_msg.val.negotiate_group.contracts_up_status[i];
+               vres_up->vres[i] = vres_msg.val.negotiate_group.vres_up[i];
+       }
+       vres_up->size = contracts_up->size;
+       for (i = 0; i < vres_down->size; i++)
+               vres_down_status[i] = vres_msg.val.negotiate_group.vres_down_status[i];
+       if (vres_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(vres_msg.error, "error(s) during contract negotiation/cancellation");
+
+       return FRSH_NO_ERROR;
+}
+
+int change_mode(bool sync,
+       const frsh_contracts_group_t *contracts_new_vres,
+       frsh_vres_group_t *vres_id_new,
+       const frsh_contracts_group_t *contracts_update_vres,
+       const frsh_vres_group_t *vres_update,
+       const frsh_vres_group_t *vres_removed,
+       frsh_signal_t signal_notify,
+       frsh_signal_info_t signal_info);
+
+/*
+ * frsh_group_change_mode_sync()
+ *
+ * ...
+ */
+int frsh_group_change_mode_sync(const frsh_contracts_group_t *contracts_new_vres,
+       frsh_vres_group_t *vres_id_new,
+       const frsh_contracts_group_t *contracts_update_vres,
+       const frsh_vres_group_t *vres_update,
+       const frsh_vres_group_t *vres_removed)
+{
+       frsh_signal_info_t null_siginfo;
+
+       null_siginfo.sival_int = 0;
+
+       return change_mode(true, contracts_new_vres, vres_id_new,
+               contracts_update_vres, vres_update, vres_removed,
+               FRSH_NULL_SIGNAL, null_siginfo);
+}
+
+/*
+ * frsh_group_change_mode_async()
+ *
+ * ...
+ */
+int frsh_group_change_mode_async(const frsh_contracts_group_t *contracts_new_vres,
+       frsh_vres_group_t *vres_id_new,
+       const frsh_contracts_group_t *contracts_update_vres,
+       const frsh_vres_group_t *vres_update,
+       const frsh_vres_group_t *vres_removed,
+       const frsh_signal_t signal_notify,
+       const frsh_signal_info_t signal_info)
+
+{
+       // new_contract_labels ???
+       return change_mode(false, contracts_new_vres, vres_id_new,
+               contracts_update_vres, vres_update, vres_removed,
+               signal_notify, signal_info);
+}
+
+int change_mode(bool sync,
+       const frsh_contracts_group_t *contracts_up,
+       frsh_vres_group_t *vres_up,
+       const frsh_contracts_group_t *new_contracts_touch,
+       const frsh_vres_group_t *vres_touch,
+       const frsh_vres_group_t *vres_down,
+       frsh_signal_t signal_notify,
+       frsh_signal_info_t signal_info)
+{
+       frsh_in_msg_t contract_msg;
+       frsh_out_msg_t vres_msg;
+       int i;
+
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                       "place a call frsh_init first!");
+       if ((new_contracts_touch == NULL && vres_touch != NULL) ||
+                       (new_contracts_touch != NULL && vres_touch == NULL))
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                       "inconsistent status of contracts and vres groups to be renengotiated");
+       if (new_contracts_touch != NULL &&
+                       vres_touch != NULL &&
+                       new_contracts_touch->size != vres_touch->size)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                       "inconsistent status of contracts and vres groups to be renengotiated");
+       if (contracts_up == NULL &&
+                       new_contracts_touch == NULL &&
+                       vres_down == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                       "nothing to do!");
+       if (!sync &&
+                       ((vres_touch != NULL && vres_touch->size == 0) &&
+                       (vres_down != NULL && vres_down->size == 0)))
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                       "at least one renegotiation or cancellation needed");
+       /* contact the service thread for contract negotiation */
+       if (sync)
+               contract_msg.type = FRSH_MT_CHANGE_MODE_SYNC;
+       else
+               contract_msg.type = FRSH_MT_CHANGE_MODE_ASYNC;
+       if (contracts_up != NULL)
+               for (i = 0; i < contracts_up->size; i++) {
+                       if (contracts_up->contracts[i] == NULL)
+                               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                                       "could not negotiate a NULL contract in the group");
+                       if (!contracts_up->contracts[i]->d_equals_t)            // limited by by this implementation
+                               PERROR_AND_RETURN(FRSH_ERR_NOT_IMPLEMENTED,
+                                       "only deadline=period implemented!");
+                       contract_msg.val.change_mode.contracts_up[i] = *(contracts_up->contracts[i]);
+               }
+       contract_msg.val.change_mode.contracts_up_number = contracts_up->size;
+       if (new_contracts_touch != NULL)
+               for (i = 0; i < new_contracts_touch->size; i++) {
+                       if (new_contracts_touch->contracts[i] == NULL)
+                               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                                       "could not change mode for a NULL contract");
+                       if (!new_contracts_touch->contracts[i]->d_equals_t)
+                               PERROR_AND_RETURN(FRSH_ERR_NOT_IMPLEMENTED,
+                                       "only deadline=period implemented!");
+                       contract_msg.val.change_mode.contracts_touch[i] = *(new_contracts_touch->contracts[i]);
+                       contract_msg.val.change_mode.vres_touch[i] = vres_touch->vres[i];
+               }
+       contract_msg.val.change_mode.contracts_touch_number = new_contracts_touch->size;
+       if (vres_down != NULL)
+               for (i = 0; i < vres_down->size; i++)
+                       contract_msg.val.negotiate_group.vres_down[i] = vres_down->vres[i];
+       contract_msg.val.negotiate_group.vres_down_number = vres_down->size;
+#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
+       contract_msg.val.change_mode.signal = signal_notify;
+       contract_msg.val.change_mode.siginfo = signal_info;
+       contract_msg.val.change_mode.thread_to_signal = fosa_thread_self();
+#endif
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &contract_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,     // it's _service_ thread, not scheduler !!
+                       "service thread not/wrong responding");
+       for (i = 0; i < contracts_up->size; i++) {
+               contracts_up_status[i] = vres_msg.val.change_mode.contracts_up_status[i];
+               vres_up->vres[i] = vres_msg.val.change_mode.vres_up[i];
+       }
+       for (i = 0; i < new_contracts_touch->size; i++)
+               vres_touch_status[i] = vres_msg.val.change_mode.vres_touch_status[i];
+       for (i = 0; i < vres_down->size; i++)
+               vres_down_status[i] = vres_msg.val.change_mode.vres_down_status[i];
+       if (sync)
+               if (vres_msg.error != FRSH_NO_ERROR)
+                       PERROR_AND_RETURN(vres_msg.error, "error(s) during contract negotiation/cancellation");
+
+       return FRSH_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// O B T A I N   I N F O R M A T I O N S   F R O M   T H E   S C H E D U L  E R
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * frsh_config_is_admission_test_enabled()
+ *
+ * Tell the caller if the admission test is enabled... And it's always enabled
+ * in this implementation!
+ *
+ * possible return values:
+ *  true
+ */
+bool frsh_config_is_admission_test_enabled()
+{
+       /* admission test is always enabled in this implementation */
+       return true;
+}
+
+/*
+ * frsh_vres_get_usage()
+ *
+ * Obtains from the service thread the CPU usage count of a vres.
+ *
+ * Note this service is only available for vres with a REGULAR contract type.
+ *
+ * As usual only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_cputime()'
+ * in the frsh_service_th.c source file
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres or contract type)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread) *  
+ */
+int frsh_vres_get_usage(const frsh_vres_id_t vres, struct timespec *spent)
+{
+       frsh_in_msg_t vres_msg;
+       frsh_out_msg_t cputime_msg;
+
+#ifdef DEBUG
+       strncpy(FUNCNAME, "frsh_vres_get_usage", 20);
+#endif
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (spent == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return in a NULL spent");
+       /* prepare the message */
+       vres_msg.type = FRSH_MT_GET_CPUTIME;
+       vres_msg.val.get_cputime.vres_id = vres;
+       /* contact the service thread for the usage retrieval */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &vres_msg, &cputime_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (cputime_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(cputime_msg.error,
+                               "can't get the renegotiation status");
+       /* renegotiation_stratus pointer untouched if something has gone wrong */
+       *spent = cputime_msg.val.get_cputime.cputime;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_vres_get_remaining_budget()
+ *
+ * Obtains from the service thread the actual remaining budget
+ * of a vres (independently by the contract type).
+ *
+ * As usual only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_current_budget()'
+ * in the frsh_service_th.c source file
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread) *  
+ */
+int frsh_vres_get_remaining_budget(const frsh_vres_id_t vres, struct timespec *budget)
+{
+       frsh_in_msg_t vres_msg;
+       frsh_out_msg_t budget_msg;
+
+#ifdef DEBUG
+       strncpy(FUNCNAME, "frsh_vres_get_remaining_budget", 31);
+#endif
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (budget == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return in a NULL budget");
+       /* prepare the message */
+       vres_msg.type = FRSH_MT_GET_CURRENTBUDGET;
+       vres_msg.val.get_currentbudget.vres_id = vres;
+       /* contact the service thread for the usage retrieval */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &vres_msg, &budget_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (budget_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(budget_msg.error,
+                               "can't get the remaining budget");
+       /* budget pointer untouched if something has gone wrong */
+       *budget = budget_msg.val.get_currentbudget.currentbudget;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_vres_get_budget_and_period()
+ *
+ * Obtains from the service thread the actual budget and period contracted
+ * for a vres (independently by the contract type).
+ *
+ * As usual only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_budget_and_period()'
+ * in the frsh_service_th.c source file
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_vres_get_budget_and_period(const frsh_vres_id_t vres,
+       struct timespec *budget,
+       struct timespec *period)
+{
+       frsh_in_msg_t vres_msg;
+       frsh_out_msg_t params_msg;
+
+#ifdef DEBUG
+       strncpy(FUNCNAME, "frsh_vres_get_budget_and_period", 33);
+#endif
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (budget == NULL || period == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return in a NULL budget or period");
+       /* prepare the message */
+       vres_msg.type = FRSH_MT_GET_BUDGET_AND_PERIOD;
+       vres_msg.val.get_budget_and_period.vres_id = vres;
+       /* contact the service thread for the usage retrieval */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &vres_msg, &params_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (params_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(params_msg.error,
+                               "can't get budget and period");
+       /* budget and period pointers untouched if something has gone wrong */
+       *budget = params_msg.val.get_budget_and_period.budget;
+       *period = params_msg.val.get_budget_and_period.period;
+
+       return FRSH_NO_ERROR;
+}
+
+/////////////////////////////////////////////
+// S E R V I C E   T H R E A D   T U N I N G
+/////////////////////////////////////////////
+
+/*
+ * frsh_service_thread_set_data(), adapt timing guarantees for the service thread
+ *
+ * Modifies the execution period and budget of the service thread from the
+ * defaults configured for it and negotiated during service thread
+ * initialization.
+ *
+ * Here we only request the operation sending a message to the service thread
+ * itself (and waiting for the answer), check the service thread main code
+ * in the frsh_service_th.c source file for the implementation details.
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL or inconsistent budget or period)
+ *  FRSH_ERR_CONTRACT_REJECTED(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread) *
+ */
+int frsh_service_thread_set_data(const struct timespec *budget,
+       const struct timespec *period,
+       bool *accepted)
+{
+       frsh_in_msg_t params_msg;
+       frsh_out_msg_t ack_msg;
+
+#ifdef DEBUG
+       strncpy(FUNCNAME, "frsh_service_thread_set_data", 29);
+#endif
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (budget == NULL || period == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't setup a NULL budget or period");
+       if (frsh_rel_time_smaller(*period, *budget))
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't setup a budget greather than the period");
+       /* prepare the message */
+       params_msg.type = FRSH_MT_SET_SERVICE_THREAD_DATA;
+       params_msg.val.set_service_thread_data.budget = *budget;
+       params_msg.val.set_service_thread_data.period = *period;
+       /* contact the service thread for the usage retrieval */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &params_msg, &ack_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (ack_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(ack_msg.error,
+                       "can't setup service thread budget and period");
+       *accepted = ack_msg.val.set_service_thread_data.accepted;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_service_thread_get_data(), obtain timing guarantees for the service thread
+ *
+ * Obtains the actual execution period and budget of the service.
+ *
+ * Here we only request the operation sending a message to the service thread
+ * itself (and waiting for the answer), check the service thread main code
+ * in the frsh_service_th.c source file for the implementation details.
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL budget or period)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ *  FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread) *
+ */
+int frsh_service_thread_get_data(frsh_rel_time_t *budget, frsh_rel_time_t *period)
+{
+       frsh_in_msg_t request_msg;
+       frsh_out_msg_t params_msg;
+
+#ifdef DEBUG
+       strncpy(FUNCNAME, "frsh_service_thread_get_data", 29);
+#endif
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (budget == NULL || period == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return results in a NULL budget or period");
+       /* prepare the message */
+       request_msg.type = FRSH_MT_GET_SERVICE_THREAD_DATA;
+       /* contact the service thread for the usage retrieval */
+       if (frsh_service_th_ask_for(frsh_service_th_pid, &request_msg, &params_msg) != FRSH_SERVICE_TH_NO_ERROR)
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
+                               "can't receive correct answer from the service thread");
+       if (params_msg.error != FRSH_NO_ERROR)
+               PERROR_AND_RETURN(params_msg.error,
+                               "can't obtain current service thread budget and period");
+       /* budget and period pointers untouched if something has gone wrong */
+       *budget = params_msg.val.get_budget_and_period.budget;
+       *period = params_msg.val.get_budget_and_period.period;
+
+       return FRSH_NO_ERROR;
+}
+
+
index f57d7fb878180549c036704a06127427a3b49e25..c9accf16519e8115e9d2b7aa35a55abeae4471ff 100644 (file)
@@ -35,5 +35,9 @@ frsh_sched_ops aquosa_sched_ops = {
        .create_vres = aquosa_create_vres();
        .cancel_vres = aquosa_cancel_vres();
        .change_vres = aquosa_change_vres();
+       /*
+        *.get_vres_usage
+        *.get_remaining_budget
+        */
 };
 
diff --git a/frsh_aquosa/synchobj.c b/frsh_aquosa/synchobj.c
new file mode 100644 (file)
index 0000000..bff5edc
--- /dev/null
@@ -0,0 +1,729 @@
+
+//synchobj_repo_t synchobj_repo;       /* defined downward, after the type definition! */
+
+/*
+ * synchronization objects repository
+ *
+ * data structure and macro declaration for the handling of the repository
+ * of synchronization objects needed by the API implementation.
+ * It's used only in the core API module so no problem implementing it all
+ * in this file without affecting the header files in frsh/include with
+ * such an implementation specific and tighted issue
+ *
+ * Note that mutual exclusive access is implemented both for the repository
+ * as a whole and for each single element to maximize the achievable
+ * parallelism and concurrency execution of threads
+ *
+ * Note also the synchronization object (subsection of the core) API is
+ * implemented within this file, without any request to the service thread,
+ * and so all "remain" local to a single process!
+ */
+
+/* data structures */
+
+typedef struct synchobj_repo_entry {
+       frsh_mutex_t mutex;
+       fosa_cond_t sync;
+       int events;
+       int queued;
+} synchobj_repo_entry_t;
+
+typedef struct synchobj_repo {
+       synchobj_repo_entry_t repo[FRSH_MAX_N_SYNCH_OBJECTS];
+       int synchobj_number;
+       frsh_mutex_t mutex;
+} synchobj_repo_t;
+
+synchobj_repo_t synchobj_repo; /* global variable */
+
+/* macro and functions */
+
+/*
+ * access functions to the repository
+ *
+ * some simple macro which help keep synchobj_repo_t opaque
+ * for the sake of code cleanness
+ */
+
+/* given the handle of a synchronization object returns its index into the
+ * repository (frsh_synchobj_handle_t remains opaque) */
+#define synchobj_handle_2_ind(h) \
+ ( h )
+/* given the index of a synchronization object in the repository returns
+ * an handle to it (frsh_synchobj_handle_t remains opaque)*/
+#define synchobj_ind_2_handle(i) \
+ ( i )
+/* given a handle of a synchronization object returns a pointer to
+ * its entry into the repository */
+#define get_synchobj_entry(handle) \
+( & ( synchobj_repo.repo[synchobj_handle_2_ind(handle)] ) )
+/* return a pointer to the synchronization object repository mutex */
+#define get_synchobj_repo_mutex() \
+ ( & ( synchobj_repo.mutex ) )
+/* gives the actual number of synchronization objects in the repository */
+#define get_synchobj_number() \
+ ( synchobj_repo.synchobj_number )
+
+/*
+ * consistency and status checks
+ *
+ * common used checkings and tests about the access to the repository
+ * and the status of each entry
+ */
+
+/* are we accessing the repository with a valid index value ? */
+#define check_synchobj_repo_ind(ind) \
+ ( ( ind >= 0 && ind < FRSH_MAX_N_SYNCH_OBJECTS ) ? true: false )
+/* is the repository entry (correctly accessed and) free ? */
+#define check_synchobj_repo_entry_free(ind)                    \
+ ( ( (check_synchobj_repo_ind(ind)) &&                         \
+  synchobj_repo.repo[ind].events == -1 ) ? true : false )
+/* is the repository entry (correctly accessed and) non free ? */
+#define check_synchobj_repo_entry_nonfree(ind)                 \
+ ( ( (check_synchobj_repo_ind(ind)) &&                         \
+  synchobj_repo.repo[ind].events != -1 ) ? true : false )
+
+/*
+ * initialize the repository
+ *
+ * sets all entries to invalid (that is, free) and init
+ * the "global" mutexe
+ *
+ * possible return values:
+ *  true (all ok)
+ *  false (something wrong with the mutex)
+ */
+static inline bool synchobj_repo_init()
+{
+       int i;
+
+       if (fosa_mutex_init(&synchobj_repo.mutex, 0) != 0)
+               return false;
+
+       synchobj_repo.synchobj_number = 0;
+       for (i = 0; i < FRSH_MAX_N_SYNCH_OBJECTS; i++) {
+               synchobj_repo.repo[i].events = -1;
+               synchobj_repo.repo[i].queued = -1;
+       }
+
+       return true;
+}
+
+/*
+ * add an entry
+ *
+ * adds an entry into the repository. If successful the index of the entry is
+ * returned in vres_ind.
+ *
+ * We suppose the caller where to place the new entry and "suggests" us a
+ * free repository entry in synchobj_ind. We then check if it's really free
+ * and, if yes, we add the entry right there.
+ * If, on the other way, the entry is not free we need to search the whole
+ * repository for a suitable place.
+ *
+ * possible return values:
+ *  true (entry correctly added)
+ *  false (entry not added, maybe no more room in the repository!)
+ */
+static inline bool synchobj_repo_put(int *synchobj_ind)
+{
+
+       int i;
+       bool result;
+
+       /* lock the repository */
+       fosa_mutex_lock(&synchobj_repo.mutex);
+       /* try to place the new entry in the caller provided position (if any)
+        * and, only if it's not free, scan all the repository for
+        * a different and suitable place */
+       if (synchobj_ind != NULL &&
+                       check_synchobj_repo_entry_free(*synchobj_ind % FRSH_MAX_N_SYNCH_OBJECTS))
+               i = *synchobj_ind % FRSH_MAX_N_SYNCH_OBJECTS;
+       else {
+               i = 0;
+               while (i < FRSH_MAX_N_SYNCH_OBJECTS && !check_synchobj_repo_entry_free(i))
+                       i++;
+       }
+       /* if we're sure it's valid and free we place the
+        * thread entry into the repository in position 'i' */
+       result = false;
+       if (check_synchobj_repo_entry_free(i)) {
+               if (fosa_mutex_init(&synchobj_repo.repo[i].mutex, 0) != 0)
+                       return false;
+               if (fosa_cond_init(&synchobj_repo.repo[i].sync) != 0)
+                       return false;
+               synchobj_repo.repo[i].events = 0;
+               synchobj_repo.repo[i].queued = 0;
+               if (synchobj_ind != NULL)
+                       *synchobj_ind = i;
+               result = true;
+       }
+
+       /* unlock the repository */
+       fosa_mutex_unlock(&synchobj_repo.mutex);
+
+       return result;
+}
+
+/*
+ * remove an entry
+ *
+ * sets the entry as free (if it already is not) and decrement the counter
+ *
+ * possible return values:
+ *  true (all ok, entry was non-free and is now free)
+ *  false (something wrong, entry was already free or index is out of renge)
+ */
+static inline bool synchobj_repo_free(const int synchobj_ind)
+{
+       bool result;
+
+       /* lock the whole repository */
+       fosa_mutex_lock(&synchobj_repo.mutex);
+
+       result = false;
+       if (check_synchobj_repo_entry_nonfree(synchobj_ind)) {
+               fosa_mutex_destroy(&synchobj_repo.repo[synchobj_ind].mutex);
+               fosa_cond_destroy(&synchobj_repo.repo[synchobj_ind].sync);
+               synchobj_repo.repo[synchobj_ind].events = -1;
+               synchobj_repo.repo[synchobj_ind].queued = -1;
+               synchobj_repo.synchobj_number--;
+               result = true;
+       }
+
+       /* unlock the whole repository */
+       fosa_mutex_unlock(&synchobj_repo.mutex);
+
+       return result;
+}
+
+/*
+ * is an entry free ?
+ *
+ * check if a specific entry of the repository can be considered free
+ * (we need do it with an atomic lock)
+ *
+ * possible return values:
+ *  true (entry is free)
+ *  false (entry is not free or index is out of range)
+ */
+static inline bool synchobj_repo_isfree(const int synchobj_ind)
+{
+       bool result;
+
+       /* lock the repository */
+       fosa_mutex_lock(&synchobj_repo.mutex);
+
+       result = check_synchobj_repo_entry_free(synchobj_ind);
+
+       /* unlock the repository */
+       fosa_mutex_unlock(&synchobj_repo.mutex);
+
+       return result;
+}
+
+/////////////////////////////////////////////////
+// S Y N C H R O N I Z A T I O N   O B J E C T S
+/////////////////////////////////////////////////
+
+/*
+ * This section is implemented much differently from how it's described
+ * in the docs since the synchronization object are not unusable from
+ * INDETERMINATE workload type thread (remember we actually we're
+ * only handling such a type of vres!!), but they simply provide, for them,
+ * a conditional [timed] wait/signal mechanism as available and implemented in
+ * many OSs and threading library.
+ *
+ * In INDETERMINATE workloads, of course, a wait request on an synchronization
+ * object (or a timed wait request) does not imply the end of the current job
+ * nor cause any budget to be "returned", since no jobs are defined for them.
+ *
+ * In BUONDED workloads, when they'll be implemented here, we can flawlessy
+ * realize the API docs' semantic and consider end-job signals and budget
+ * return
+ *
+ * Note that, beside the peculiarity of this implementation being the
+ * orthogonality with respect to threads and processes, all the
+ * synchronization objects API section is implemented without bothering the
+ * service thread, so it remains local to the single process and usable from
+ * its various threads to synchronize themself, i.e. it is by no way usable in
+ * order to synchronize different processes or different threads among
+ * different processes between each other!
+ */
+
+/*
+ * frsh_synchobj_create(), create a synchronization object
+ *
+ * Note FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD and
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY are never returned as errors within
+ * this implementation
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL synchronization object handle)
+ *  FRSH_ERR_TOO_MANY_SYNCH_OBJECTS
+ *  FRSH_ERR_INTERNAL_ERROR (something, different from previous, went wrong)
+ */
+int frsh_synchobj_create(frsh_synchobj_handle_t *synch_handle)
+{
+       int synch_ind;
+
+#ifdef DEBUG
+       strncpy(FUNCNAME, "frsh_synchobj_create", 21);
+#endif
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (synch_handle == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't return a synchronization object in a NULL synch_handle");
+
+       /* add the object and return an handler to it */
+       if (synchobj_repo_put(&synch_ind))
+               *synch_handle = synchobj_ind_2_handle(synch_ind);
+       else
+               /* something wrong, try to guess what */
+               if (get_synchobj_number() >= FRSH_MAX_N_SYNCH_OBJECTS)
+                       /* synchronization object max number reached */
+                       PERROR_AND_RETURN(FRSH_ERR_TOO_MANY_SYNCH_OBJS,
+                                       "can't create any more synchronization objects");
+               else
+                       /* unspecified error (this should almost never be reached) */
+                       PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                       "can't create the synchronization objects");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_synchobj_destroy(), destroy a synchronization object
+ *
+ * Note we check if wakeing up some threads is needed and we do this while
+ * holding a lock on the synchronization object, acquired while holding
+ * a lock on the whole repository in order to prevent races
+ *
+ * Note FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD and
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY are never returned as errors within
+ * this implementation too
+ *
+ * possible return value:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE
+ *  FRSH_ERR_INTERNAL_ERROR (something, different from previous, went wrong)
+ */
+int frsh_synchobj_destroy(const frsh_synchobj_handle_t synch_handle)
+{
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (synchobj_repo_isfree(synchobj_handle_2_ind(synch_handle)))
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE,
+                               "can't destroy a synchronization object from an invalid synch_handle");
+
+       /* get an exclusive access lock to the synchronization object
+        * while holding the exclusive access to the whole repository for the
+        * sake of safetyness */
+       fosa_mutex_lock(get_synchobj_repo_mutex());
+       fosa_mutex_lock(&(get_synchobj_entry(synch_handle)->mutex));
+       fosa_mutex_unlock(get_synchobj_repo_mutex());
+       /* have I got to wake up someone ?? */
+       while (get_synchobj_entry(synch_handle)->queued > 0) {
+               if (fosa_cond_signal(&(get_synchobj_entry(synch_handle)->sync)) != 0) {
+                       fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+                       fosa_mutex_unlock(get_synchobj_repo_mutex());
+                       PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                       "can't wake up blocked threads while destroying the synchronization object");
+               } else
+                       get_synchobj_entry(synch_handle)->queued--;
+       }
+       /* release the lock on the synchronization object */
+       fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+
+       /* remove the synchronization object from the repository */
+       if (!synchobj_repo_free(synchobj_handle_2_ind(synch_handle)))
+               /* unspecified error (this should almost never be reached) */
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't delete the synchronization objects");
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_synchobj_wait() and frsh_synchobj_wit_with_timeout
+ *
+ * They're very very much similar between each other so we choose to implement
+ * them using a single generic function with a few more parameters to
+ * discriminate the two behaviours, avoiding a lot of code replication
+ */
+
+static int synchobj_wait(bool with_timeoout,           /* forward declaration of the generic wait function */
+       const frsh_synchobj_handle_t synch_handle,
+       const struct timespec *abs_timeout,
+       bool *timed_out,
+       struct timespec *next_budget,
+       struct timespec *next_period,
+       bool *was_deadline_missed,
+       bool *was_budget_overran);
+
+/*
+ * frsh_synchobj_wait(), stop the thread till signaled by another one
+ *
+ * Implements the standard behaviour of a wait for a condition to be verified
+ * and signaled by another thread of the process.
+ *
+ * As stated before is perfectly usable even by the INDETERMINATE workloads
+ * for whom it does not represent the 'end job' event.
+ *
+ * It's implemented simply by a call to the generic function coded below
+ *
+ * Note FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD and
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY are never returned as errors within
+ * this implementation and also FRSH_ERR_WORKLOAD_NOT_COMPATIBLE
+ * is ignored by us
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE (invalid synch. object or too many thread queued on it)
+ *  all that frsh_thread_get_vres_id returns (FRSH_ERR_NOT_BOUND, )
+ *  FRSH_ERR_INTERNAL_ERROR (something wrong trying to wait on the object)
+ */
+int frsh_synchobj_wait(const frsh_synchobj_handle_t synch_handle,
+       frsh_rel_time_t *next_budget,
+       frsh_rel_time_t *next_period,
+       bool *was_deadline_missed,
+       bool *was_budget_overran)
+{
+       /* simply call the generic function asking for a wait without any timeout */
+       return synchobj_wait(false, synch_handle, NULL, NULL, next_budget, next_period,
+                       was_deadline_missed, was_budget_overran);
+}
+
+/*
+ * frsh_synchobj_wait_with_timeout(), stop the thread till a timeout or a signal by another one
+ *
+ * Implements the standard behaviour of a wait for a condition to be verified
+ * and signaled by another thread of the process with a max. timeout value
+ *
+ * It's exactly the same as 'frsh_synchobj_wait()' with the only difference of
+ * the timeout and so it's, again, implemented simply by a call to the generic
+ * function with the correct parameters
+ *
+ * Note FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD and
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY are never returned as errors within
+ * this implementation and also FRSH_ERR_WORKLOAD_NOT_COMPATIBLE
+ * is ignored by us
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE (invalid synch. object or too many thread queued on it)
+ *  all that 'frsh_thread_get_vres_id()' returns (FRSH_ERR_NOT_BOUND, )
+ *  FRSH_ERR_INTERNAL_ERROR (something wrong trying to wait on the object)
+ */
+int frsh_synchobj_wait_with_timeout(
+       const frsh_synchobj_handle_t synch_handle,
+       const frsh_abs_time_t *abs_timeout,
+       bool *timed_out,
+       frsh_rel_time_t *next_budget,
+       frsh_rel_time_t *next_period,
+       bool *was_deadline_missed,
+       bool *was_budget_overran)
+{
+       /* simply call the generic function asking for a wait with the specified timeout */
+       return synchobj_wait(true, synch_handle, abs_timeout, timed_out, next_budget, next_period,
+                       was_deadline_missed, was_budget_overran);
+}
+
+/*
+ * generic function definition:
+ *  it _really_ implements both (depending on the parameters)
+ *  wait on synchronization objects API calls
+ */
+static int synchobj_wait(bool with_timeout,    /* discriminating parameter between the two functions */
+       const frsh_synchobj_handle_t synch_handle,
+       const struct timespec *abs_timeout,
+       bool *timed_out,
+       struct timespec *next_budget,
+       struct timespec *next_period,
+       bool *was_deadline_missed,
+       bool *was_budget_overran)
+{
+       frsh_thread_id_t thread_self;
+       qres_sid_t thread_sid;
+       qres_time_t qres_thread_budget;
+       struct timespec tmp_thread_budget, tmp_thread_period;
+       frsh_vres_id_t vres_id;
+       int frsh_status, timedwait_status;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       /* check the thread is running with a negotiated contract */
+       thread_self = fosa_thread_self();
+       thread_sid = FRSH_QRES_NOT_VALID_SID;
+       vres_id = FRSH_NOT_VALID_VRES_ID;
+       /* ask AQuoSA directly, if it's succesfull we can avoid a call to
+        * the service thread that is much less overhead!! */
+       if (qres_get_sid(thread_self.linux_pid, thread_self.linux_tid, &thread_sid) == QOS_E_NOSERVER)
+               /* maybe we're bounded to a background vres and, in order
+                * of being sure, we need to ask the service thread :-( */
+               if ( (frsh_status = frsh_thread_get_vres_id(thread_self, &vres_id)) != FRSH_NO_ERROR)
+                       PERROR_AND_RETURN(frsh_status,
+                                       "can't wait if the thread is not bound to any vres");
+       if (synchobj_repo_isfree(synchobj_handle_2_ind(synch_handle)))
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE,
+                               "can't wait on an synchronization object via an invalid synch_handler");
+
+       /* acquire the exclusive access lock on the synchronization object
+        * while holding it on the whole repository */
+       fosa_mutex_lock(get_synchobj_repo_mutex());
+       fosa_mutex_lock(&(get_synchobj_entry(synch_handle)->mutex));
+       fosa_mutex_unlock(get_synchobj_repo_mutex());
+
+       /* check if we can wait on the object or the limit has already been reached */
+       if ((get_synchobj_entry(synch_handle)->events == 0) &&
+                       (get_synchobj_entry(synch_handle)->queued >= FRSH_MAX_N_VRES_IN_SYNCH_OBJECT)) {
+               fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+               PERROR_AND_RETURN(FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE,
+                               "can't queue more vres on this synchronization object");
+       }
+       /* we need to wait only if there are no ready events */
+       if (!get_synchobj_entry(synch_handle)->events) {
+               /* inform we're going to suspend oursef! */
+               get_synchobj_entry(synch_handle)->queued++;
+               if (with_timeout) {
+                       *timed_out = false;
+                       timedwait_status = fosa_cond_timedwait(&(get_synchobj_entry(synch_handle)->sync),
+                                       &(get_synchobj_entry(synch_handle)->mutex),
+                                       abs_timeout);
+                       if (timedwait_status != 0) {
+                               if (timedwait_status == ETIMEDOUT) {
+                                       /* no signal event before the timeout */
+                                       *timed_out = true;
+                                       get_synchobj_entry(synch_handle)->events++;     /* preventive increment */
+                               } else {
+                                       /* some other strange error! */
+                                       fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+                                       PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                               "can't wait on the synchronization object");
+                               }
+                       }
+               } else
+                       if (fosa_cond_wait(&(get_synchobj_entry(synch_handle)->sync),
+                                       &(get_synchobj_entry(synch_handle)->mutex)) != 0) {
+                               fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+                               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                               "can't wait on the syncrhonization object");
+                       }
+               /* the synchronization object is still valid? */
+               if (synchobj_repo_isfree(synchobj_handle_2_ind(synch_handle)))
+                       /* no, someone destroyed our synchronization object! */
+                       PERROR_AND_RETURN(FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE,
+                                       "synchronization object no longer valid, it has been destroyed during wait");
+               get_synchobj_entry(synch_handle)->queued--;
+       }
+       get_synchobj_entry(synch_handle)->events--;
+       /* all done, release the lock on the synchronization object */
+       fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+
+       /* now retreive timing (budget and period) parameters, don't care about
+        * overruns (remember we're always WT_INDETERMINATE) and make them 
+        * both 'false' */
+       if (next_period != NULL || (next_budget != NULL && thread_sid == -1)) {
+               /* ask the service thread only if it's strictly necessary !! */
+               if (vres_id == FRSH_NOT_VALID_VRES_ID)
+                       /* we need to know (from the service thread) the vres_id */
+                       if ( (frsh_status = frsh_thread_get_vres_id(thread_self, &vres_id)) != FRSH_NO_ERROR)
+                               PERROR_AND_RETURN(frsh_status,
+                                               "can't gather vres info for period and budget retrieval");
+               if (frsh_vres_get_budget_and_period(vres_id,
+                       &tmp_thread_budget,
+                       &tmp_thread_period) != FRSH_NO_ERROR)
+                       PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                       "can't get vres/contract budget and period");
+       }
+       if (next_budget != NULL) {
+               if (thread_sid == FRSH_QRES_NOT_VALID_SID)
+                       /* background thread, we use the contracted budget
+                        * retrieved previously */
+                       *next_budget = tmp_thread_budget;
+               else {
+                       /* regular thread, ask for the actual budget direclty to AQuoSA
+                        * (much less overhead !!) */
+                       if (qres_get_curr_budget(thread_sid, &qres_thread_budget) != QOS_OK)
+                               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                               "can't get the actual budget for the vres");
+                       usec_to_timespec(*next_budget, qres_thread_budget);
+               }
+       }
+       if (next_period != NULL)
+               *next_period = tmp_thread_period;
+       if (was_deadline_missed != NULL)
+               was_deadline_missed = false;
+       if (was_budget_overran != NULL)
+               was_budget_overran = false;
+
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_synchobj_signal(), notify a synchronization object
+ *
+ * Remember if noone is waiting for the notification it is queued in the
+ * synchronization objects
+ *
+ * Note FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD and
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY are never returned as errors within
+ * this implementation too
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (invalid synch_handle)
+ *  FRSH_ERR_TOO_MANY_EVENTS_IN_SYNCH_OBJ
+ */
+int frsh_synchobj_signal(const frsh_synchobj_handle_t synch_handle)
+{
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (synchobj_repo_isfree(synchobj_handle_2_ind(synch_handle)))
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't signal a synchronization object via an invalid synch_handle");
+       /* acquire the exclusive access lock on the synchronization object
+        * while holding it on the whole repository */
+       fosa_mutex_lock(get_synchobj_repo_mutex());
+       fosa_mutex_lock(&(get_synchobj_entry(synch_handle)->mutex));
+       fosa_mutex_unlock(get_synchobj_repo_mutex());
+
+       if (get_synchobj_entry(synch_handle)->events >= FRSH_MAX_N_EVENTS_IN_SYNCH_OBJECT) {
+               fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+               PERROR_AND_RETURN(FRSH_ERR_TOO_MANY_EVENTS_IN_SYNCH_OBJ,
+                               "can't enqueue more events on the synchronization object");
+       }
+       get_synchobj_entry(synch_handle)->events++;
+
+       /* release the lock */
+       fosa_mutex_unlock(&(get_synchobj_entry(synch_handle)->mutex));
+       /* and, finally, signal the condition */
+       fosa_cond_signal(&(get_synchobj_entry(synch_handle)->sync));
+       
+       return FRSH_NO_ERROR;
+}
+
+/*
+ * frsh_timed_wait(), sleep until specified absolute time
+ *
+ * Again, it does not imply 'end job' or any budget modification for
+ * INDETERMINATE workload vres, simply wait for the timer to fire!
+ *
+ * The timeout is implemented via the 'clock_nanosleep()' function
+ * (we need to consider a fosa wrapper for it too) in order to get rid
+ * of all the problems related to signal handling in a multithreaded
+ * environment (and even because it's the simplest and best suited
+ * solution for the acheiving what we need to!!)
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL abs_time)
+ *  FRSH_ERR_INTERNAL_ERROR (FRSH_ERR_TIME_SPEC_IN_THE_PAST)
+ *  FRSH_ERR_INTERNAL_ERROR (something wrong with timer and/or signal handling)
+ *  all that 'frsh_thread_get_vres_id()' returns (FRSH_ERR_NOT_BOUND, )
+ */
+
+int frsh_timed_wait (
+       const frsh_abs_time_t *abs_time,
+       frsh_rel_time_t *next_budget,
+       frsh_rel_time_t *next_period,
+       bool *was_deadline_missed,
+       bool *was_budget_overran)
+{
+       frsh_thread_id_t thread_self;
+       qres_sid_t thread_sid;
+       qres_time_t qres_thread_budget;
+       struct timespec tmp_thread_budget, tmp_thread_period;
+       frsh_vres_id_t vres_id;
+       frsh_abs_time_t actual_time, rm_time;
+       int frsh_status;
+
+       /* check for framework initialization and arguments */
+       if (!frsh_initialized)
+               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
+                               "can't proceed before initializing FRSH with 'frsh_init()'!");
+       if (abs_time == NULL)
+               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
+                               "can't wait for a NULL abs_time");
+       /* check the thread is running with a negotiated contract */
+       thread_self = fosa_thread_self();
+       thread_sid = FRSH_QRES_NOT_VALID_SID;
+       vres_id = FRSH_NOT_VALID_VRES_ID;
+       if (qres_get_sid(thread_self.linux_pid, thread_self.linux_tid, &thread_sid) == QOS_E_NOSERVER)
+               /* maybe we're bounded to a background vres and, in order
+                * of being sure, we need to ask the service thread :-( */
+               if ( (frsh_status = frsh_thread_get_vres_id(thread_self, &vres_id)) != FRSH_NO_ERROR)
+                       PERROR_AND_RETURN(frsh_status,
+                                       "can't get the vres id the calling thread is associated with");
+       /* check the provided absolute time reference is in the future */
+       if (fosa_clock_get_time(FOSA_CLOCK_REALTIME, &actual_time) < 0)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't get the current time");
+       if (frsh_abs_time_smaller(*abs_time, actual_time))
+               //PERROR_AND_RETURN(FRSH_ERR_TIME_SPEC_IN_THE_PAST,
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't wait for a past absolute time");
+       /* put the thread to sleep for the requested interval */
+       if (clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, abs_time, &rm_time) < 0)
+               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                               "can't put the thread to sleep");
+       /* if ( <check, via rm_time, if we've been interrupted> )
+        *      ... ... ...
+        *      ... ... ... */
+       /* retreive timing (budget and period) parameters, don't care about
+        * overruns (remember we're always WT_INDETERMINATE) and make them 
+        * both 'false' */
+       if (next_period != NULL || (next_budget != NULL && thread_sid == FRSH_QRES_NOT_VALID_SID)) {
+               /* ask the service thread only if it's strictly necessary !! */
+               if (vres_id == FRSH_NOT_VALID_VRES_ID)
+                       /* we need to know (from the service thread) the vres_id !! */
+                       if ( (frsh_status = frsh_thread_get_vres_id(thread_self, &vres_id)) != FRSH_NO_ERROR)
+                               PERROR_AND_RETURN(frsh_status,
+                                               "can't gather vres info for period and budget retrieval");
+               if (frsh_vres_get_budget_and_period(vres_id,
+                       &tmp_thread_budget,
+                       &tmp_thread_period) != FRSH_NO_ERROR)
+                       PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                       "can't get vres/contract budget and period");
+       }
+       if (next_budget != NULL) {
+               if (thread_sid == FRSH_QRES_NOT_VALID_SID)
+                       /* background thread, we use the contracted budget
+                        * retrieved previously */
+                       *next_budget = tmp_thread_budget;
+               else {
+                       /* regular thread, ask for the actual budget direclty to AQuoSA
+                        * (much less overhead !!) */
+                       if (qres_get_curr_budget(thread_sid, &qres_thread_budget) != QOS_OK)
+                               PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
+                                               "can't get the actual budget for the vres");
+                       usec_to_timespec(*next_budget, qres_thread_budget);
+               }
+       }
+       if (next_period != NULL)
+               *next_period = tmp_thread_period;
+       if (was_deadline_missed != NULL)
+               *was_deadline_missed = false;
+       if (was_budget_overran != NULL)
+               *was_budget_overran = false;
+
+       return FRSH_NO_ERROR;
+}
+
index 29e9d09f921f0a69449eac812e051216a5613beb..f21f4285956829c734777e48f7f86416a83e73cf 100644 (file)
@@ -5,29 +5,7 @@
 
 int fwp_fna_init(const frsh_resource_id_t resource_id);
 {
-       fwp_init();
-}
-
-/** FNA negotiate routine */
-
-int fwp_fna_contract_negotiate
-       (const frsh_resource_id_t resource_id,
-       const frsh_contract_t *contract,
-       fna_vres_id_t *vres)
-{
-       struct fwp_contract cnt;
-       int res;
-
-       /* copy to fwp_contract */
-       cnt.period_usec = contract->period;
-       cnt.budget = contract->budget;
-       
-       res = fwp_negotiate(&cnt);
-       if (res < 0) 
-               return -1;
-
-       *vres = res;
-       return 0;
+       return fwp_init();
 }
 
 
@@ -97,21 +75,13 @@ int fwp_fna_receive_async(const fna_endpoint_data_t *endpoint, void *buffer,
                               from, MSG_DONTWAIT);
 }
 
-int fwp_fna_receive_endpoint_created (void)
-{
-       INADDR_ANY
-       fwp_receive_endpoint_create(fwp_configuration.my_node_id,..);
-
-}
-
-
 int fwp_fna_vres_destroy(const frsh_resource_id_t resource_id,
                     const fna_vres_id_t vres)
 {
        return fwp_vres_close(vres);    
 }
 
-/*fna_operations_t fwp_fna_operations = {
+fna_operations_t fwp_fna_operations = {
     .fna_init = fwp_fna_init,
     .fna_contract_negotiate = NULL,
     .fna_contract_renegotiate_sync = NULL,
@@ -136,4 +106,4 @@ int fwp_fna_vres_destroy(const frsh_resource_id_t resource_id,
     .fna_network_bytes_to_budget = NULL,
     .fna_network_budget_to_bytes = NULL,
     .fna_network_get_min_eff_budget = NULL
-}*/
+}