mb_time_util.h
author Edouard Tisserant <edouard.tisserant@gmail.com>
Mon, 07 Jun 2021 11:21:26 +0200
changeset 17 e319814f1c17
parent 0 ae252e0fd9b8
permissions -rw-r--r--
merge
0
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     1
/*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     2
 * Copyright (c) 2002,2016 Mario de Sousa (msousa@fe.up.pt)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     3
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     4
 * This file is part of the Modbus library for Beremiz and matiec.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     5
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     6
 * This Modbus library is free software: you can redistribute it and/or modify
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     7
 * it under the terms of the GNU Lesser General Public License as published by
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     8
 * the Free Software Foundation, either version 3 of the License, or
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     9
 * (at your option) any later version.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    10
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    11
 * This program is distributed in the hope that it will be useful, but
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    14
 * General Public License for more details.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    15
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    16
 * You should have received a copy of the GNU Lesser General Public License
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    17
 * along with this Modbus library.  If not, see <http://www.gnu.org/licenses/>.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    18
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    19
 * This code is made available on the understanding that it will not be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    20
 * used in safety-critical situations without a full and competent review.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    21
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    22
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    23
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    24
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    25
 /* Time handling functions used by the modbus protocols... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    26
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    27
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    28
#ifndef __MODBUS_TIME_UTIL_H
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    29
#define __MODBUS_TIME_UTIL_H
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    30
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    31
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    32
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    33
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    34
/**     Time format conversion     **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    35
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    36
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    37
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    38
/* Function to load a struct timeval correctly from a double. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    39
static inline struct timeval d_to_timeval(double time) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    40
  struct timeval tmp;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    41
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    42
  tmp.tv_sec  = time;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    43
  tmp.tv_usec = 1e6*(time - tmp.tv_sec);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    44
  return tmp;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    45
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    46
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    47
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    48
/* Function to load a struct timespec correctly from a double. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    49
static inline struct timespec d_to_timespec(double time) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    50
  struct timespec tmp;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    51
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    52
  tmp.tv_sec  = time;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    53
  tmp.tv_nsec = 1e9*(time - tmp.tv_sec);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    54
  return tmp;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    55
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    56
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    57
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    58
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    59
/* Function to ... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    60
static inline struct timespec timespec_dif(struct timespec ts1, struct timespec ts2) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    61
  struct timespec ts;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    62
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    63
  ts.tv_sec  = ts1.tv_sec  - ts2.tv_sec;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    64
  if(ts1.tv_nsec > ts2.tv_nsec) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    65
    ts.tv_nsec = ts1.tv_nsec - ts2.tv_nsec;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    66
  } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    67
    ts.tv_nsec = 1000000000 + ts1.tv_nsec - ts2.tv_nsec;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    68
    ts.tv_sec--;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    69
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    70
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    71
  if (ts.tv_sec < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    72
    ts.tv_sec = ts.tv_nsec = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    73
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    74
  return ts;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    75
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    76
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    77
/* Function to ... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    78
static inline struct timespec timespec_add(struct timespec ts1, struct timespec ts2) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    79
  struct timespec ts;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    80
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    81
  ts.tv_sec  = ts1.tv_sec  + ts2.tv_sec;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    82
  ts.tv_nsec = ts1.tv_nsec + ts2.tv_nsec;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    83
  ts.tv_sec += ts.tv_nsec / 1000000000;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    84
  ts.tv_nsec = ts.tv_nsec % 1000000000;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    85
  return ts;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    86
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    87
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    88
/* Function to convert a struct timespec to a struct timeval. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    89
static inline struct timeval timespec_to_timeval(struct timespec ts) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    90
  struct timeval tv;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    91
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    92
  tv.tv_sec  = ts.tv_sec;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    93
  tv.tv_usec = ts.tv_nsec/1000;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    94
  return tv;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    95
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    96
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    97
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    98
/*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    99
 * NOTE: clock_gettime() is rather expensive, between 7000 and 7500 clock
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   100
 *       cycles (measured with rdtsc on an Intel Pentium)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   101
 *       gettimeofday() is half as expensive (3000 to 3500 clock cycles),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   102
 *       but is not POSIX compliant... :-(
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   103
 *       Nevertheless this is peanuts (20 us on a 350 MHz cpu) compared to
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   104
 *       the timescales required to read a modbus frame over a serial bus
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   105
 *       (aprox. 10 ms for a 10 byte frame on a 9600 baud bus!)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   106
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   107
static inline struct timespec timespec_add_curtime(struct timespec ts) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   108
  struct timespec  res     = {.tv_sec = 0, .tv_nsec = 0};
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   109
  
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   110
  /* is ts = 0 also return 0 !! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   111
  if ((ts.tv_sec != 0) || (ts.tv_nsec != 0))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   112
    if (clock_gettime(CLOCK_MONOTONIC, &res) >= 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   113
      res = timespec_add(res, ts);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   114
  return res;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   115
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   116
  
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   117
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   118
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   119
/** select() with absolute timeout **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   120
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   121
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   122
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   123
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   124
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   125
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   126
/* My private version of select using an absolute timeout, instead of the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   127
 * usual relative timeout.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   128
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   129
 * NOTE: Ususal select semantics for (a: end_time == NULL) and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   130
 *       (b: *end_time == 0) also apply.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   131
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   132
 *       (a) Indefinite timeout
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   133
 *       (b) Try once, and and quit if no data available.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   134
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   135
/* Returns: -1 on error
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   136
 *           0 on timeout
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   137
 *          >0 on success
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   138
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   139
static int my_select(int fd, fd_set *rfds, fd_set *wfds, const struct timespec *end_time) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   140
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   141
  int res;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   142
  struct timespec cur_time;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   143
  struct timeval timeout, *tv_ptr;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   144
  fd_set tmp_rfds, *tmp_rfds_ptr, tmp_wfds, *tmp_wfds_ptr;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   145
  
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   146
  tmp_rfds_ptr = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   147
  tmp_wfds_ptr = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   148
  if (rfds != NULL) tmp_rfds_ptr = &tmp_rfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   149
  if (wfds != NULL) tmp_wfds_ptr = &tmp_wfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   150
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   151
  /*============================*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   152
   * wait for data availability *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   153
   *============================*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   154
  do {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   155
    if (rfds != NULL) tmp_rfds = *rfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   156
    if (wfds != NULL) tmp_wfds = *wfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   157
      /* NOTE: To do the timeout correctly we would have to revert to timers
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   158
       *       and asociated signals. That is not very thread friendly, and is
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   159
       *       probably too much of a hassle trying to figure out which signal
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   160
       *       to use. What if we don't have any free signals?
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   161
       *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   162
       *       The following solution is not correct, as it includes a race
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   163
       *       condition. The following five lines of code should really
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   164
       *       be atomic!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   165
       *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   166
       * NOTE: see also the timeout related comment in the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   167
       *       modbus_tcp_read() function!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   168
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   169
    if (end_time == NULL) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   170
      tv_ptr = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   171
    } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   172
      tv_ptr = &timeout;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   173
      if ((end_time->tv_sec == 0) && (end_time->tv_nsec == 0)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   174
        timeout.tv_sec = timeout.tv_usec = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   175
      } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   176
        /* ATOMIC - start */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   177
        if (clock_gettime(CLOCK_MONOTONIC, &cur_time) < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   178
          return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   179
        timeout = timespec_to_timeval(timespec_dif(*end_time, cur_time));
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   180
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   181
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   182
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   183
    res = select(fd, tmp_rfds_ptr, tmp_wfds_ptr, NULL, tv_ptr);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   184
  /* ATOMIC - end */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   185
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   186
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   187
  {int i;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   188
   if (tmp_rfds_ptr != NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   189
     for (i = 0; i < fd; i++)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   190
       if (FD_ISSET(i, tmp_rfds_ptr))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   191
         fprintf(stderr,"fd=%d is ready for reading\n", i);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   192
   if (tmp_wfds_ptr != NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   193
     for (i = 0; i < fd; i++)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   194
       if (FD_ISSET(i, tmp_wfds_ptr))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   195
         fprintf(stderr,"fd=%d is ready for writing\n", i);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   196
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   197
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   198
    if (res == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   199
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   200
      printf("Comms time out\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   201
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   202
      return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   203
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   204
    if ((res < 0) && (errno != EINTR)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   205
      return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   206
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   207
  } while (res <= 0);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   208
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   209
  if (rfds != NULL) *rfds = tmp_rfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   210
  if (wfds != NULL) *wfds = tmp_wfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   211
  return res;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   212
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   213
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   214
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   215
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   216
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   217
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   218
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   219
#endif  /* __MODBUS_TIME_UTIL_H */