1/*
2 * ptw32_relmillisecs.c
3 *
4 * Description:
5 * This translation unit implements miscellaneous thread functions.
6 *
7 * --------------------------------------------------------------------------
8 *
9 *      Pthreads-win32 - POSIX Threads Library for Win32
10 *      Copyright(C) 1998 John E. Bossom
11 *      Copyright(C) 1999,2005 Pthreads-win32 contributors
12 *
13 *      Contact Email: rpj@callisto.canberra.edu.au
14 *
15 *      The current list of contributors is contained
16 *      in the file CONTRIBUTORS included with the source
17 *      code distribution. The list can also be seen at the
18 *      following World Wide Web location:
19 *      http://sources.redhat.com/pthreads-win32/contributors.html
20 *
21 *      This library is free software; you can redistribute it and/or
22 *      modify it under the terms of the GNU Lesser General Public
23 *      License as published by the Free Software Foundation; either
24 *      version 2 of the License, or (at your option) any later version.
25 *
26 *      This library is distributed in the hope that it will be useful,
27 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
28 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29 *      Lesser General Public License for more details.
30 *
31 *      You should have received a copy of the GNU Lesser General Public
32 *      License along with this library in the file COPYING.LIB;
33 *      if not, write to the Free Software Foundation, Inc.,
34 *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
35 */
36
37#include "pthread.h"
38#include "implement.h"
39#if !defined(NEED_FTIME)
40#include <sys/timeb.h>
41#endif
42
43
44#if defined(PTW32_BUILD_INLINED)
45INLINE
46#endif /* PTW32_BUILD_INLINED */
47DWORD
48ptw32_relmillisecs (const struct timespec * abstime)
49{
50  const int64_t NANOSEC_PER_MILLISEC = 1000000;
51  const int64_t MILLISEC_PER_SEC = 1000;
52  DWORD milliseconds;
53  int64_t tmpAbsMilliseconds;
54  int64_t tmpCurrMilliseconds;
55#if defined(NEED_FTIME)
56  struct timespec currSysTime;
57  FILETIME ft;
58  SYSTEMTIME st;
59#else /* ! NEED_FTIME */
60#if ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \
61    ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 )
62  struct __timeb64 currSysTime;
63#else
64  struct _timeb currSysTime;
65#endif
66#endif /* NEED_FTIME */
67
68
69  /*
70   * Calculate timeout as milliseconds from current system time.
71   */
72
73  /*
74   * subtract current system time from abstime in a way that checks
75   * that abstime is never in the past, or is never equivalent to the
76   * defined INFINITE value (0xFFFFFFFF).
77   *
78   * Assume all integers are unsigned, i.e. cannot test if less than 0.
79   */
80  tmpAbsMilliseconds =  (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
81  tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
82
83  /* get current system time */
84
85#if defined(NEED_FTIME)
86
87  GetSystemTime(&st);
88  SystemTimeToFileTime(&st, &ft);
89  /*
90   * GetSystemTimeAsFileTime(&ft); would be faster,
91   * but it does not exist on WinCE
92   */
93
94  ptw32_filetime_to_timespec(&ft, &currSysTime);
95
96  tmpCurrMilliseconds = (int64_t)currSysTime.tv_sec * MILLISEC_PER_SEC;
97  tmpCurrMilliseconds += ((int64_t)currSysTime.tv_nsec + (NANOSEC_PER_MILLISEC/2))
98			   / NANOSEC_PER_MILLISEC;
99
100#else /* ! NEED_FTIME */
101
102#if defined(_MSC_VER) && _MSC_VER >= 1400
103  _ftime64_s(&currSysTime);
104#elif ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \
105      ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 )
106  _ftime64(&currSysTime);
107#else
108  _ftime(&currSysTime);
109#endif
110
111  tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC;
112  tmpCurrMilliseconds += (int64_t) currSysTime.millitm;
113
114#endif /* NEED_FTIME */
115
116  if (tmpAbsMilliseconds > tmpCurrMilliseconds)
117    {
118      milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds);
119      if (milliseconds == INFINITE)
120        {
121          /* Timeouts must be finite */
122          milliseconds--;
123        }
124    }
125  else
126    {
127      /* The abstime given is in the past */
128      milliseconds = 0;
129    }
130
131  return milliseconds;
132}
133