]> rtime.felk.cvut.cz Git - frescor/fna.git/commitdiff
michael found an error in the definition of the posix sporadic servers so i replaced...
authorsangorrin <sangorrin@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Mon, 21 Apr 2008 17:35:20 +0000 (17:35 +0000)
committersangorrin <sangorrin@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Mon, 21 Apr 2008 17:35:20 +0000 (17:35 +0000)
git-svn-id: http://www.frescor.org/private/svn/frescor/fna/trunk@1131 35b4ef3e-fd22-0410-ab77-dab3279adceb

src_frescan/frescan.c
src_frescan/frescan_data.h
src_frescan/frescan_debug.h
src_frescan/frescan_queues.c
src_frescan/frescan_servers.c
src_frescan/frescan_servers.c_posix [new file with mode: 0644]
src_frescan/frescan_servers.h
src_frescan/frescan_servers_replenishments.c
src_frescan/frescan_servers_replenishments.c_posix [new file with mode: 0644]
src_frescan/frescan_servers_replenishments.h

index 5ec15fa4f64870a351434c25ee805cc837b660c0..fcfcf973c79d08e3b82cb7a8b8a2032266eaec6b 100644 (file)
@@ -35,7 +35,6 @@
 #include "frescan_id.h"        // frescan_id_set_field, frescan_id_get_field
 #include "frescan_hw_buffer.h" // frescan_hw_buffer_update
 #include "frescan_bwres_robjs.h"     // frescan_replyobjects_init
-#include "frescan_servers_replenishments.h" // frescan_replenishments_xxx
 #include "frescan_packets.h"
 
 static int frescan_hook_frame_recv (const struct can_chip_t *chip,
@@ -151,12 +150,6 @@ int frescan_init(frescan_init_params_t *params)
                 return -1;
         }
 
-        ret = frescan_replenishments_init(params->net);
-        if (ret != 0) {
-                ERROR("could not initialize the replenishments\n");
-                return -1;
-        }
-
         return 0;
 }
 
@@ -532,15 +525,7 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip)
                 DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
                       "calling frame_sent + program repl for id:%u\n", id);
 
-                ret = frescan_replenishment_program(chip->minor,
-                                                    id,
-                                                    &packet->timestamp);
-                if (ret != 0) {
-                        ERROR("could not program replenishment\n");
-                        return -1;
-                }
-
-                ret = frescan_servers_frame_sent(chip->minor, id);
+                ret = frescan_servers_frame_sent(chip->minor, id, packet);
                 if (ret != 0) {
                         ERROR("could not let the server a frame was sent\n");
                         return -1;
index b857d8776d0b140cea8222da0d3743c871e08147..2c7070c195f144e4c826b067a28ad29d326cafe1 100644 (file)
@@ -35,7 +35,6 @@
 #include "frescan.h"         // frescan_node_t, _prio_t, _budget_t
 #include "frescan_config.h"  // FRESCAN_MLOCK_T, FRESCAN_MX_XXX
 #include "frescan_packets.h" // frescan_packet_t
-#include "frescan_servers_replenishments.h" // frescan_repl_op_t
 
 /**
  * frescan_repl_op_t - a replenishment operation
@@ -80,7 +79,9 @@ typedef struct {
  * @repl_list: the list of pending replenishment operations
  * @repl_timer: the timer for the replenishments associated to this server
  *     NOTE: we could use a single timer for all but for now this is simpler
+ * @act_time: the last activation time for the server
  * @packet_list: the packets enqueued on this server
+ * @servers_list: the list of servers
  */
 
 typedef struct {
@@ -92,6 +93,7 @@ typedef struct {
         frescan_budget_t  pending_packets;
         frescan_repl_op_t replenishments;
         timer_t           repl_timer;
+        struct timespec   act_time;
         frescan_packet_t  packet_list;
         struct list_head  servers_list;
 } frescan_server_data_t;
index 63f96b8addd42a03c7d3752c84ceb451cadb0371..18909e24b29da485560a5ed574eefb3aea5823af 100644 (file)
@@ -40,7 +40,7 @@
  * DEBUGGING FLAGS to enable/disable debugging messages
  **/
 
-#define FRESCAN_SERVERS_ENABLE_DEBUG    false
+#define FRESCAN_SERVERS_ENABLE_DEBUG    true
 #define FRESCAN_PACKETPOOL_ENABLE_DEBUG false
 #define FRESCAN_FRAG_ENABLE_DEBUG       false
 #define FRESCAN_INIT_ENABLE_DEBUG       false
 #define FRESCAN_SENT_HOOK_ENABLE_DEBUG  false
 #define FRESCAN_QUEUES_ENABLE_DEBUG     false
 #define FRESCAN_HW_BUFFER_ENABLE_DEBUG  false
-#define FRESCAN_REPLENSH_ENABLE_DEBUG   false
+#define FRESCAN_REPLENSH_ENABLE_DEBUG   true
 #define FRESCAN_ROBJS_ENABLE_DEBUG      false
-#define FRESCAN_BWRES_ENABLE_DEBUG      true
+#define FRESCAN_BWRES_ENABLE_DEBUG      false
 #define FRESCAN_REQUESTS_ENABLE_DEBUG   false
-#define FRESCAN_MANAGER_ENABLE_DEBUG    true
-#define FRESCAN_ACCEPTOR_ENABLE_DEBUG   true
+#define FRESCAN_MANAGER_ENABLE_DEBUG    false
+#define FRESCAN_ACCEPTOR_ENABLE_DEBUG   false
 #define FRESCAN_FNA_ENABLE_DEBUG        false
 #define FRESCAN_MESSAGES_ENABLE_DEBUG   false
 
index 681c7161d7ccf7ee40f703fee355e26de66f1aed..b6ae28a2b08d017264db76ca989c9231d05c9f77 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <stdlib.h>
 #include <time.h>
+#include <misc/timespec_operations.h>
 
 #include "frescan_queues.h"
 #include "frescan_packets.h"
@@ -284,24 +285,26 @@ int frescan_servers_enqueue(frescan_network_t net,
                             frescan_ss_t id,
                             frescan_packet_t *packet)
 {
-        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "enqueue packet for id:%u\n", id);
+        frescan_server_data_t *server = &the_servers_pool[net][id];
 
         clock_gettime (CLOCK_MONOTONIC, &packet->timestamp);
 
+        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "id:%u timestamp:(%d, %d)\n",
+              id, packet->timestamp.tv_sec, packet->timestamp.tv_nsec);
+
         // add the packet to the server fifo list
-        list_add_tail(&packet->fifo_list,
-                       &the_servers_pool[net][id].packet_list.fifo_list);
+        list_add_tail(&packet->fifo_list, &server->packet_list.fifo_list);
 
-        // if the server was inactive (no packets to send) put it active
-        // (in the active list)
-        if (the_servers_pool[net][id].pending_packets == 0) {
+        // if the server was inactive (no packets) put it in the active list
+        if (server->pending_packets == 0) {
                 DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
-                      "server was inactive, put in the active list\n");
-                list_add_tail(&the_servers_pool[net][id].servers_list,
-                               &the_active_servers[net].servers_list);
+                      "ss becomes active act_time=timestamp\n");
+                list_add_tail(&server->servers_list,
+                              &the_active_servers[net].servers_list);
+                server->act_time = packet->timestamp;
         }
 
-        the_servers_pool[net][id].pending_packets++;
+        server->pending_packets++;
         return 0;
 }
 
@@ -354,30 +357,33 @@ int frescan_servers_dequeue(frescan_network_t net,
                             frescan_prio_t *packet_prio)
 {
         struct list_head *pos;
+        frescan_server_data_t *server;
 
-        if (list_empty(&the_servers_pool[net][id].packet_list.fifo_list)) {
+        server = &the_servers_pool[net][id];
+
+        if (list_empty(&server->packet_list.fifo_list)) {
                 ERROR("no packet in server %d fifo list\n", id);
                 return -1;
         }
 
-        list_for_each(pos, &the_servers_pool[net][id].packet_list.fifo_list) {
+        list_for_each(pos, &server->packet_list.fifo_list) {
                 *packet = list_entry(pos, frescan_packet_t, fifo_list);
                 break;
         }
 
         list_del(&((*packet)->fifo_list));
-        *packet_prio = the_servers_pool[net][id].current_priority;
-        the_servers_pool[net][id].pending_packets--;
+        *packet_prio = server->current_priority;
+        server->pending_packets--;
 
-        if (the_servers_pool[net][id].pending_packets == 0) {
+        if (server->pending_packets == 0) {
                 DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
                       "no more packets, delete from active list\n");
-                list_del(&the_servers_pool[net][id].servers_list);
+                list_del(&server->servers_list);
         }
 
         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
               "dequeued packet server:%u cur_prio:%u pending:%u\n",
-              id, *packet_prio, the_servers_pool[net][id].pending_packets);
+              id, *packet_prio, server->pending_packets);
 
         return 0;
 }
index 3d8198448f847d6273a6db55eac4a3b134cc7938..52562b6209ab8233990f22ce2ccd81cb5213d6ae 100644 (file)
  */
 
 #include "frescan_servers.h"
+#include "frescan_servers_replenishments.h" // frescan_replenishments_xxx
 #include "frescan_debug.h"
 #include "frescan_data.h"
 #include <misc/linux_list.h>
+#include <misc/timespec_operations.h>
 #include <signal.h>
+#include <time.h>
 
 /**
  * frescan_servers_init() - initialize server structures
@@ -47,6 +50,12 @@ int frescan_servers_init(frescan_network_t net)
                 INIT_LIST_HEAD(&the_active_servers[net].servers_list);
         }
 
+        ret = frescan_replenishments_init(net);
+        if (ret != 0) {
+                ERROR("could not initialize the replenishments\n");
+                return -1;
+        }
+
         return 0;
 }
 
@@ -63,8 +72,10 @@ int frescan_servers_create(frescan_network_t net,
                            const frescan_server_params_t *params,
                            frescan_ss_t *id)
 {
-        int ret, pos;
+        int i, ret, pos;
         struct sigevent evp;
+        frescan_server_data_t *server;
+        frescan_repl_op_t *repl;
 
         FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
         pos = freelist_alloc(&the_servers_pool_freelist[net]);
@@ -77,23 +88,37 @@ int frescan_servers_create(frescan_network_t net,
 
         *id = (frescan_ss_t)pos;
 
-        the_servers_pool[net][*id].net = net;
-        the_servers_pool[net][*id].id  = *id;
-        the_servers_pool[net][*id].params = *params;
-        the_servers_pool[net][*id].current_budget = params->values.budget;
-        the_servers_pool[net][*id].current_priority = params->prio;
-        the_servers_pool[net][*id].pending_packets = 0;
-
-        INIT_LIST_HEAD(&the_servers_pool[net][*id].replenishments.repl_list);
-        INIT_LIST_HEAD(&the_servers_pool[net][*id].packet_list.fifo_list);
+        server = &the_servers_pool[net][*id];
+
+        server->net = net;
+        server->id  = *id;
+        server->params = *params;
+        server->current_budget = params->values.budget;
+        server->current_priority = params->prio;
+        server->pending_packets = 0;
+
+        // the first act_time is set to the server creation time
+        clock_gettime (CLOCK_MONOTONIC, &server->act_time);
+
+        // init the list of packets associated to the server
+        INIT_LIST_HEAD(&server->packet_list.fifo_list);
+
+        // allocate the replenishment capacity queue
+        INIT_LIST_HEAD(&server->replenishments.repl_list);
+        for (i=0; i < params->values.budget; i++) {
+                repl = frescan_repl_op_alloc();
+                repl->when = server->act_time;
+                repl->amount = 1;
+                list_add_tail(&repl->repl_list,
+                              &server->replenishments.repl_list);
+        }
 
         // the repl timer sends a signal when it expires with the server id
         evp.sigev_notify = SIGEV_SIGNAL;
         evp.sigev_signo  = FRESCAN_REPL_SIGNAL_NUM;
         evp.sigev_value.sival_int  = (int)*id;
 
-        ret = timer_create (CLOCK_MONOTONIC,
-                            &evp, &the_servers_pool[net][*id].repl_timer);
+        ret = timer_create (CLOCK_MONOTONIC, &evp, &server->repl_timer);
         if (ret != 0) {
                 ERROR("could not create timer\n");
                 return ret;
@@ -101,9 +126,7 @@ int frescan_servers_create(frescan_network_t net,
 
         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
               "server created, id:%u budget:%u prio:%u\n",
-              *id,
-              the_servers_pool[net][*id].params.values.budget,
-              the_servers_pool[net][*id].params.prio);
+              *id, server->params.values.budget, server->params.prio);
 
         return 0;
 }
@@ -250,27 +273,25 @@ int frescan_servers_get_highest_prio(frescan_network_t net,
  * function at frescan_servers_replenishments module
  */
 
-int frescan_servers_frame_sent(frescan_network_t net, frescan_ss_t id)
+int frescan_servers_frame_sent(frescan_network_t net,
+                               frescan_ss_t id,
+                               frescan_packet_t *packet)
 {
-        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
-              "id:%u, current_budget:%u, current_priority:%u\n",
-              id,
-              the_servers_pool[net][id].current_budget,
-              the_servers_pool[net][id].current_priority);
-
-        if (the_servers_pool[net][id].current_budget > 0) {
-                the_servers_pool[net][id].current_budget--;
-                if (the_servers_pool[net][id].current_budget == 0) {
-                        the_servers_pool[net][id].current_priority =
-                                        FRESCAN_BACKGROUND_PRIO;
+        int ret;
+        struct timespec *repl_time;
+        frescan_server_data_t *server;
+
+        server = &the_servers_pool[net][id];
+
+        if (server->current_priority != FRESCAN_BACKGROUND_PRIO) {
+                if (smaller_timespec(&packet->timestamp, &server->act_time)) {
+                        repl_time = &server->act_time;
+                } else {
+                        repl_time = &packet->timestamp;
                 }
+                ret = frescan_replenishment_program(net, id, repl_time);
+                if (ret != 0) return -1;
         }
 
-        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
-              "now... id:%u, current_budget:%u, current_priority:%u\n",
-              id,
-              the_servers_pool[net][id].current_budget,
-              the_servers_pool[net][id].current_priority);
-
         return 0;
 }
diff --git a/src_frescan/frescan_servers.c_posix b/src_frescan/frescan_servers.c_posix
new file mode 100644 (file)
index 0000000..3196b94
--- /dev/null
@@ -0,0 +1,301 @@
+/*!
+ * @file frescan_servers.c
+ *
+ * @brief FRESCAN sporadic servers
+ *
+ * @version 0.01
+ *
+ * @date 27-Feb-2008
+ *
+ * @author
+ *      Daniel Sangorrin
+ *
+ * @comments
+ *
+ * This file contains the FRESCAN sporadic servers that allow to isolate
+ * different streams of data by assigning them a budget and replenishment
+ * period.
+ *
+ * @license
+ *
+ * See MaRTE OS license
+ *
+ */
+
+#include "frescan_servers.h"
+#include "frescan_servers_replenishments.h" // frescan_replenishments_xxx
+#include "frescan_debug.h"
+#include "frescan_data.h"
+#include <misc/linux_list.h>
+#include <misc/timespec_operations.h>
+#include <signal.h>
+#include <time.h>
+
+/**
+ * frescan_servers_init() - initialize server structures
+ *
+ * @net: the network instance
+ */
+
+int frescan_servers_init(frescan_network_t net)
+{
+        int ret, i;
+
+        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "initializing servers\n");
+
+        ret = freelist_init(&the_servers_pool_freelist[net], FRESCAN_MX_IDS);
+        if (ret != 0) return ret;
+
+        for (i=0; i<FRESCAN_MX_NETWORKS; i++) {
+                INIT_LIST_HEAD(&the_active_servers[net].servers_list);
+        }
+
+        ret = frescan_replenishments_init(net);
+        if (ret != 0) {
+                ERROR("could not initialize the replenishments\n");
+                return -1;
+        }
+
+        return 0;
+}
+
+/**
+ * frescan_servers_create() - create a sporadic server
+ *
+ * @net: the network instance
+ * @params: the parameters for the server
+ * @id: the identificator for the server as a return value
+ *
+ */
+
+int frescan_servers_create(frescan_network_t net,
+                           const frescan_server_params_t *params,
+                           frescan_ss_t *id)
+{
+        int ret, pos;
+        struct sigevent evp;
+
+        FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
+        pos = freelist_alloc(&the_servers_pool_freelist[net]);
+        FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
+
+        if (pos == -1) {
+                ERROR("could not allocate servers\n");
+                return -1;
+        }
+
+        *id = (frescan_ss_t)pos;
+
+        the_servers_pool[net][*id].net = net;
+        the_servers_pool[net][*id].id  = *id;
+        the_servers_pool[net][*id].params = *params;
+        the_servers_pool[net][*id].current_budget = params->values.budget;
+        the_servers_pool[net][*id].current_priority = params->prio;
+        the_servers_pool[net][*id].pending_packets = 0;
+
+        // the first act_time is set to the server creation time
+        clock_gettime (CLOCK_MONOTONIC, &the_servers_pool[net][*id].act_time);
+
+        INIT_LIST_HEAD(&the_servers_pool[net][*id].replenishments.repl_list);
+        INIT_LIST_HEAD(&the_servers_pool[net][*id].packet_list.fifo_list);
+
+        // the repl timer sends a signal when it expires with the server id
+        evp.sigev_notify = SIGEV_SIGNAL;
+        evp.sigev_signo  = FRESCAN_REPL_SIGNAL_NUM;
+        evp.sigev_value.sival_int  = (int)*id;
+
+        ret = timer_create (CLOCK_MONOTONIC,
+                            &evp, &the_servers_pool[net][*id].repl_timer);
+        if (ret != 0) {
+                ERROR("could not create timer\n");
+                return ret;
+        }
+
+        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
+              "server created, id:%u budget:%u prio:%u\n",
+              *id,
+              the_servers_pool[net][*id].params.values.budget,
+              the_servers_pool[net][*id].params.prio);
+
+        return 0;
+}
+
+/**
+ * frescan_servers_update() - update a sporadic server data
+ *
+ * @net: the network instance
+ * @params: the parameters for the server
+ * @id: the identificator for the server
+ *
+ */
+
+int frescan_servers_update(frescan_network_t net,
+                           const frescan_server_params_t *params,
+                           frescan_ss_t id)
+{
+        the_servers_pool[net][id].params = *params;
+        return 0;
+}
+
+/**
+ * frescan_servers_destroy() - delete a sporadic server
+ *
+ * @net: the network instance
+ * @id: the identificator for the server
+ *
+ */
+
+int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id)
+{
+        int ret;
+
+        // TODO: free the replenishment operations and the packets for the
+        // server.
+
+        ret = timer_delete (the_servers_pool[net][id].repl_timer);
+        if (ret != 0) {
+                ERROR("could not delete timer\n");
+                return ret;
+        }
+
+        FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
+        list_del(&the_servers_pool[net][id].servers_list);
+
+        ret = freelist_free(&the_servers_pool_freelist[net], id);
+        FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
+        if (ret != 0) {
+                ERROR("could not free server data from pool\n");
+                return ret;
+        }
+
+        return 0;
+}
+
+/**
+ * frescan_servers_get_data() - get a sporadic server data
+ *
+ * @net: the network instance
+ * @params: the parameters of the server
+ * @id: the identificator for the server
+ *
+ */
+
+int frescan_servers_get_data(frescan_network_t net,
+                             frescan_server_params_t *params,
+                             frescan_ss_t id)
+{
+        *params = the_servers_pool[net][id].params;
+        return 0;
+}
+
+/**
+ * frescan_servers_get_current_budget() - get the current sporadic server budget
+ *
+ * @net: the network instance
+ * @id: the identificator for the server
+ * @current_budget: the current budget of the server
+ *
+ */
+
+int frescan_servers_get_current_budget(frescan_network_t net,
+                                       frescan_ss_t id,
+                                       frescan_budget_t *current_budget)
+{
+        *current_budget = the_servers_pool[net][id].current_budget;
+        return 0;
+}
+
+/**
+ * frescan_servers_get_highest_prio() - get the server with highest priority
+ *
+ * @net: the network instance
+ * @id: the identificator for the server
+ * @prio: the priority of that server
+ *
+ * For each active server, check the priority.
+ * If "id" is returned with a value of FRESCAN_MX_IDS,
+ * there are no active servers.
+ * NOTE: id=FRESCAN_MX_IDS is the identifier for fixed priority messages
+ * TODO: use a priority queue of active servers
+ *
+ */
+
+int frescan_servers_get_highest_prio(frescan_network_t net,
+                                     frescan_ss_t *id,
+                                     frescan_prio_t *prio)
+{
+        frescan_server_data_t *server;
+
+        if (list_empty(&the_active_servers->servers_list)) {
+                DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "server list is empty\n");
+                *id = FRESCAN_MX_IDS;
+                return 0;
+        }
+
+        *prio = 0;
+        list_for_each_entry(server, &the_active_servers[net].servers_list,
+                            servers_list) {
+                if (server->current_priority >= *prio) {
+                        *id = server->id;
+                        *prio = server->current_priority;
+                }
+        }
+
+        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
+              "highest prio:%u id:%u\n", *prio, *id);
+
+        return 0;
+}
+
+/**
+ * frescan_servers_frame_sent() - hook to control the server budget and prio
+ *
+ * @net: the network instance
+ * @id: the identificator for the server
+ *
+ * This function is called when a frame has been effectively sent through the
+ * CAN bus and that frame is associated to a certain server. The function
+ * decreases the capacity of the server and sets the priority to background
+ * in case the budget is exhausted.
+ *
+ * NOTE: the replenishment operation is programmed using the corresponding
+ * function at frescan_servers_replenishments module
+ */
+
+int frescan_servers_frame_sent(frescan_network_t net,
+                               frescan_ss_t id,
+                               frescan_packet_t *packet)
+{
+        int ret;
+        struct timespec *repl_time;
+        frescan_server_data_t *server;
+
+        server = &the_servers_pool[net][id];
+
+        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
+              "before.. id:%u, current_budget:%u, current_priority:%u\n",
+              id, server->current_budget, server->current_priority);
+
+        if (server->current_budget > 0) {
+                server->current_budget--;
+                if (server->current_budget == 0) {
+                        server->current_priority = FRESCAN_BACKGROUND_PRIO;
+                }
+
+                if (smaller_timespec(&packet->timestamp, &server->act_time)) {
+                        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "using act_time\n");
+                        repl_time = &server->act_time;
+                } else {
+                        repl_time = &packet->timestamp;
+                }
+
+                ret = frescan_replenishment_program(net, id, repl_time);
+                if (ret != 0) return -1;
+        }
+
+        DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
+              "after.. id:%u, current_budget:%u, current_priority:%u\n",
+              id, server->current_budget, server->current_priority);
+
+        return 0;
+}
index 047225dd3762a51fa76550c5efe1bb4231f01cad..df5d43c217cab5123130c49f1dc9efa973927794 100644 (file)
@@ -122,6 +122,7 @@ extern int frescan_servers_get_highest_prio(frescan_network_t net,
  *
  * @net: the network instance
  * @id: the identificator for the server
+ * @packet: the packet sent (with its timestamp)
  *
  * This function is called when a frame has been effectively sent through the
  * CAN bus and that frame is associated to a certain server. The function
@@ -132,6 +133,8 @@ extern int frescan_servers_get_highest_prio(frescan_network_t net,
  * function at frescan_servers_replenishments module
  */
 
-extern int frescan_servers_frame_sent(frescan_network_t net, frescan_ss_t id);
+extern int frescan_servers_frame_sent(frescan_network_t net,
+                                      frescan_ss_t id,
+                                      frescan_packet_t *packet);
 
 #endif // _MARTE_FRESCAN_SERVERS_H_
index d0ea18cf2c641f75d9dd127567ea91cdb33df33a..157c36399636ea46b1354df288d5b18646c07c66 100644 (file)
@@ -55,7 +55,7 @@ static int frescan_repl_op_init()
         return freelist_init(&the_repl_op_pool_freelist, FRESCAN_MX_REPL_OPS);
 }
 
-static frescan_repl_op_t *frescan_repl_op_alloc()
+frescan_repl_op_t *frescan_repl_op_alloc()
 {
         int pos;
 
@@ -68,7 +68,7 @@ static frescan_repl_op_t *frescan_repl_op_alloc()
         return &the_repl_op_pool[pos];
 }
 
-static int frescan_repl_op_free(frescan_repl_op_t *repl_op)
+int frescan_repl_op_free(frescan_repl_op_t *repl_op)
 {
         return freelist_free(&the_repl_op_pool_freelist, repl_op->pool_pos);
 }
@@ -84,8 +84,6 @@ static void *frescan_repl_thread(void *arg)
         siginfo_t siginfo;
         frescan_ss_t id;
         frescan_network_t net;
-        struct list_head *pos;
-        frescan_repl_op_t *repl = NULL;
         frescan_server_data_t *server;
         struct itimerspec timerdata;
 
@@ -116,56 +114,12 @@ static void *frescan_repl_thread(void *arg)
                 server = &the_servers_pool[net][id];
 
                 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
-                      "id:%u, current_budget:%u, budget:%u, current_prio:%u\n",
-                      id,
-                      server->current_budget,
-                      server->params.values.budget,
-                      server->current_priority);
-
-                server->current_budget++;
-
-                if (server->current_priority == FRESCAN_BACKGROUND_PRIO) {
-                        server->current_priority = server->params.prio;
-                }
-
-                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
-                      "now... current_budget:%u, current_prio:%u\n",
-                      server->current_budget,
-                      server->current_priority);
-
-                // delete the replenishment of this call
-                list_for_each(pos, &server->replenishments.repl_list) {
-                        repl = list_entry(pos, frescan_repl_op_t, repl_list);
-                        break;
-                }
-
-                list_del(&repl->repl_list);
-
-                ret = frescan_repl_op_free(repl);
-                if (ret != 0) {
-                        ERROR("could not free replenishment op\n");
-                        return NULL;
-                }
-
-                // check if there are pending replenishments
-                if (list_empty(&server->replenishments.repl_list)) continue;
-
-                list_for_each(pos, &server->replenishments.repl_list) {
-                        repl = list_entry(pos, frescan_repl_op_t, repl_list);
-                        break;
-                }
-
-                timerdata.it_value = repl->when;
+                      "id:%u current_prio:%u\n", id, server->current_priority);
 
-                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
-                      "set timer to %d sec, %d nsec\n",
-                      repl->when.tv_sec, repl->when.tv_nsec);
+                server->current_priority = server->params.prio;
 
-                ret = timer_settime(server->repl_timer,
-                                    TIMER_ABSTIME, &timerdata, NULL);
-                if (ret != 0) {
-                        ERROR("could not set replenishment timer\n");
-                        return NULL;
+                if (!list_empty(&server->packet_list.fifo_list)) {
+                        clock_gettime (CLOCK_MONOTONIC, &server->act_time);
                 }
         }
 
@@ -247,35 +201,40 @@ int frescan_replenishment_program(frescan_network_t net,
                                   const struct timespec *timestamp)
 {
         int ret;
-        frescan_repl_op_t *repl;
-        bool empty;
+        frescan_repl_op_t *repl = NULL;
         struct itimerspec timerdata;
         frescan_server_data_t *server;
+        struct list_head *pos;
+        struct timespec now;
 
         server = &the_servers_pool[net][ss];
 
-        if (server->current_priority == FRESCAN_BACKGROUND_PRIO) {
-                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG, "ss in background\n");
-                return 0;
-        }
-
-        repl = frescan_repl_op_alloc();
-        if (repl == NULL) {
-                ERROR("could not allocate a repl operation\n");
-                return -1;
+        // extract the head
+        list_for_each(pos, &server->replenishments.repl_list) {
+                repl = list_entry(pos, frescan_repl_op_t, repl_list);
+                break;
         }
+        list_del(&repl->repl_list);
 
+        // move to tail with new repl value
         repl->when = *timestamp;
         incr_timespec (&repl->when, &server->params.values.period);
         repl->amount = 1;
 
-        empty = list_empty(&server->replenishments.repl_list);
-        DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG, "ss:%u, empty:%u\n", ss, empty);
-
         list_add_tail(&repl->repl_list,
-                      &server->replenishments.repl_list);
+                       &server->replenishments.repl_list);
+
+        // check the new head
+        list_for_each(pos, &server->replenishments.repl_list) {
+                repl = list_entry(pos, frescan_repl_op_t, repl_list);
+                break;
+        }
+
+        clock_gettime (CLOCK_MONOTONIC, &now);
+
+        if (smaller_timespec(&now, &repl->when)) {
+                server->current_priority = FRESCAN_BACKGROUND_PRIO;
 
-        if (empty) {
                 timerdata.it_interval.tv_sec  = 0;
                 timerdata.it_interval.tv_nsec = 0;
                 timerdata.it_value = repl->when;
diff --git a/src_frescan/frescan_servers_replenishments.c_posix b/src_frescan/frescan_servers_replenishments.c_posix
new file mode 100644 (file)
index 0000000..2b8e36b
--- /dev/null
@@ -0,0 +1,295 @@
+/*!
+ * @file frescan_servers_replenishments.c
+ *
+ * @brief the replenishment data and thread for the servers
+ *
+ * @version 0.01
+ *
+ * @date 12-Mar-2008
+ *
+ * @author
+ *      Daniel Sangorrin
+ *
+ * @comments
+ *
+ * This module contains the thread that waits for server's replenishment
+ * timer signals and perform the necessary replenishments.
+ *
+ * @license
+ *
+ * See MaRTE OS license
+ *
+ */
+
+#include <time.h>            // clock_gettime
+
+#include <misc/freelist.h>   // freelist_t
+#include <misc/linux_list.h> // list_add_tail
+#include <misc/timespec_operations.h>
+
+#include "frescan_servers_replenishments.h"
+#include "frescan_config.h"  // FRESCAN_MX_REPL_OPS
+#include "frescan_debug.h"   // ERROR
+#include "frescan_data.h"    // frescan_repl_op_t
+#include "fosa_threads_and_signals.h" // fosa_thread_attr_init...
+
+/**
+ * the_repl_op_pool - pool of replenishment operations
+ *
+ * We have a pool of replenishment operation structures and an associated
+ * freelist where we can get/put replenishment operations in O(1) time
+ *
+ * @the_repl_op_pool: array with the replenishment operations allocated
+ * @the_repl_op_pool_freelist: freelist for the_repl_op_pool
+ * @frescan_repl_op_init: initializes the freelist
+ * @frescan_repl_op_alloc: get a free replenishment operation structure
+ * @frescan_repl_op_free: free a replenishment operation structure
+ *
+ */
+
+static frescan_repl_op_t the_repl_op_pool[FRESCAN_MX_REPL_OPS];
+static freelist_t the_repl_op_pool_freelist;
+
+static int frescan_repl_op_init()
+{
+        return freelist_init(&the_repl_op_pool_freelist, FRESCAN_MX_REPL_OPS);
+}
+
+static frescan_repl_op_t *frescan_repl_op_alloc()
+{
+        int pos;
+
+        pos = freelist_alloc(&the_repl_op_pool_freelist);
+        if (pos == -1) {
+                ERROR("could not allocate repl op\n");
+                return NULL;
+        }
+        the_repl_op_pool[pos].pool_pos = pos; // to know how to free it
+        return &the_repl_op_pool[pos];
+}
+
+static int frescan_repl_op_free(frescan_repl_op_t *repl_op)
+{
+        return freelist_free(&the_repl_op_pool_freelist, repl_op->pool_pos);
+}
+
+/**
+ * frescan_repl_thread - the thread that executes the replenishments
+ */
+
+static void *frescan_repl_thread(void *arg)
+{
+        int ret;
+        sigset_t set;
+        siginfo_t siginfo;
+        frescan_ss_t id;
+        frescan_network_t net;
+        struct list_head *pos;
+        frescan_repl_op_t *repl = NULL;
+        frescan_server_data_t *server;
+        struct itimerspec timerdata;
+
+        net = (frescan_network_t)(uint32_t)arg;
+        timerdata.it_interval.tv_sec  = 0;
+        timerdata.it_interval.tv_nsec = 0;
+
+        sigemptyset(&set);
+        sigaddset(&set, FRESCAN_REPL_SIGNAL_NUM);
+
+        while (1) {
+                ret = sigwaitinfo(&set, &siginfo);
+                if (ret == -1) {
+                        ERROR("sigwaitinfo failed\n");
+                        return NULL;
+                }
+
+                if (siginfo.si_signo != FRESCAN_REPL_SIGNAL_NUM) continue;
+
+                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
+                      "net:%u signal:%d code:%d value(server_id):%d\n",
+                      net,
+                      siginfo.si_signo,            // FRESCAN_REPL_SIGNAL_NUM
+                      siginfo.si_code,             // SI_TIMER
+                      siginfo.si_value.sival_int); // the server id
+
+                id = siginfo.si_value.sival_int;
+                server = &the_servers_pool[net][id];
+
+                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
+                      "id:%u, current_budget:%u, budget:%u, current_prio:%u\n",
+                      id,
+                      server->current_budget,
+                      server->params.values.budget,
+                      server->current_priority);
+
+                server->current_budget++;
+
+                if (server->current_priority == FRESCAN_BACKGROUND_PRIO) {
+                        server->current_priority = server->params.prio;
+                        if (!list_empty(&server->packet_list.fifo_list)) {
+                                clock_gettime (CLOCK_MONOTONIC,
+                                               &server->act_time);
+                        }
+                }
+
+                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
+                      "now... current_budget:%u, current_prio:%u\n",
+                      server->current_budget,
+                      server->current_priority);
+
+                // delete the replenishment of this call
+                list_for_each(pos, &server->replenishments.repl_list) {
+                        repl = list_entry(pos, frescan_repl_op_t, repl_list);
+                        break;
+                }
+
+                list_del(&repl->repl_list);
+
+                ret = frescan_repl_op_free(repl);
+                if (ret != 0) {
+                        ERROR("could not free replenishment op\n");
+                        return NULL;
+                }
+
+                // check if there are pending replenishments
+                if (list_empty(&server->replenishments.repl_list)) continue;
+
+                list_for_each(pos, &server->replenishments.repl_list) {
+                        repl = list_entry(pos, frescan_repl_op_t, repl_list);
+                        break;
+                }
+
+                timerdata.it_value = repl->when;
+
+                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
+                      "set timer to (%d, %d)\n",
+                      repl->when.tv_sec, repl->when.tv_nsec);
+
+                ret = timer_settime(server->repl_timer,
+                                    TIMER_ABSTIME, &timerdata, NULL);
+                if (ret != 0) {
+                        ERROR("could not set replenishment timer\n");
+                        return NULL;
+                }
+        }
+
+        return NULL;
+}
+
+/**
+ * frescan_replenishments_init - init the replenishment structures and thread
+ *
+ * @net: the network instance
+ *
+ * Initialize the repl_op pool, set the mask for the timer signals and create
+ * the thread that will await for those signals and replenish the appropiate
+ * sporadic server.
+ */
+
+int frescan_replenishments_init(frescan_network_t net)
+{
+        int ret;
+        fosa_signal_t signal_set[1];
+        fosa_thread_attr_t attr;
+
+        ret = frescan_repl_op_init();
+        if (ret != 0) {
+                ERROR("could not init repl_op pool\n");
+                return ret;
+        }
+
+        signal_set[0] = FRESCAN_REPL_SIGNAL_NUM;
+
+        ret = fosa_set_accepted_signals(signal_set, 1);
+        if (ret != 0) {
+                ERROR("could not set the repl signal\n");
+                return ret;
+        }
+
+        // create the replenishment thread
+
+        ret = fosa_thread_attr_init(&attr);
+        if (ret != 0) {
+                ERROR("could not init thread attributes\n");
+                return ret;
+        }
+
+        ret = fosa_thread_attr_set_prio(&attr, FRESCAN_REPL_THREAD_PRIO);
+        if (ret != 0) {
+                ERROR("could not set repl thread prio %d\n",
+                      FRESCAN_REPL_THREAD_PRIO);
+                return ret;
+        }
+
+        ret = fosa_thread_create(&the_networks[net].repl_thread_id,
+                                 &attr,
+                                 frescan_repl_thread,
+                                 (void *)(uint32_t)net);
+        if (ret != 0) {
+                ERROR("could not create the replenishment thread\n");
+                return ret;
+        }
+
+        ret = fosa_thread_attr_destroy(&attr);
+        if (ret != 0) {
+                ERROR("could not destroy thread attributes\n");
+                return ret;
+        }
+
+        return 0;
+}
+
+/**
+ * frescan_replenishment_program - set a replenishment operation
+ *
+ * @net: the network instance
+ * @ss: the server
+ */
+
+int frescan_replenishment_program(frescan_network_t net,
+                                  frescan_ss_t ss,
+                                  const struct timespec *timestamp)
+{
+        int ret;
+        frescan_repl_op_t *repl;
+        bool empty;
+        struct itimerspec timerdata;
+        frescan_server_data_t *server;
+
+        server = &the_servers_pool[net][ss];
+
+        repl = frescan_repl_op_alloc();
+        if (repl == NULL) {
+                ERROR("could not allocate a repl operation\n");
+                return -1;
+        }
+
+        repl->when = *timestamp;
+        incr_timespec (&repl->when, &server->params.values.period);
+        repl->amount = 1;
+
+        empty = list_empty(&server->replenishments.repl_list);
+        DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG, "ss:%u, empty:%u\n", ss, empty);
+
+        list_add_tail(&repl->repl_list,
+                      &server->replenishments.repl_list);
+
+        if (empty) {
+                timerdata.it_interval.tv_sec  = 0;
+                timerdata.it_interval.tv_nsec = 0;
+                timerdata.it_value = repl->when;
+
+                DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
+                      "set timer to %d sec, %d nsec\n",
+                      repl->when.tv_sec, repl->when.tv_nsec);
+
+                ret = timer_settime(server->repl_timer,
+                                    TIMER_ABSTIME, &timerdata, NULL);
+                if (ret != 0) {
+                        ERROR("could not set the replenishment timer\n");
+                        return ret;
+                }
+        }
+
+        return 0;
+}
index 3d4e979423a75d85668cf696531b26c77a31e1d4..e1f9c809f70711b462294c5310e357e572258b16 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <time.h>
 #include "frescan.h" // frescan_network_t
+#include "frescan_data.h"
 
 /**
  * frescan_replenishments_init - init the replenishment structures and thread
 
 extern int frescan_replenishments_init(frescan_network_t net);
 
+extern frescan_repl_op_t *frescan_repl_op_alloc();
+
+extern int frescan_repl_op_free(frescan_repl_op_t *repl_op);
+
 /**
  * frescan_replenishment_program - set a replenishment operation
  *