1 /*
2  * pthread_timechange_handler_np.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  *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
35  */
36 
37 #include "pthread.h"
38 #include "implement.h"
39 
40 /*
41  * Notes on handling system time adjustments (especially negative ones).
42  * ---------------------------------------------------------------------
43  *
44  * This solution was suggested by Alexander Terekhov, but any errors
45  * in the implementation are mine - [Ross Johnson]
46  *
47  * 1) The problem: threads doing a timedwait on a CV may expect to timeout
48  *    at a specific absolute time according to a system timer. If the
49  *    system clock is adjusted backwards then those threads sleep longer than
50  *    expected. Also, pthreads-win32 converts absolute times to intervals in
51  *    order to make use of the underlying Win32, and so waiting threads may
52  *    awake before their proper abstimes.
53  *
54  * 2) We aren't able to distinquish between threads on timed or untimed waits,
55  *    so we wake them all at the time of the adjustment so that they can
56  *    re-evaluate their conditions and re-compute their timeouts.
57  *
58  * 3) We rely on correctly written applications for this to work. Specifically,
59  *    they must be able to deal properly with spurious wakeups. That is,
60  *    they must re-test their condition upon wakeup and wait again if
61  *    the condition is not satisfied.
62  */
63 
64 void *
pthread_timechange_handler_np(void * arg)65 pthread_timechange_handler_np (void *arg)
66      /*
67       * ------------------------------------------------------
68       * DOCPUBLIC
69       *      Broadcasts all CVs to force re-evaluation and
70       *      new timeouts if required.
71       *
72       * PARAMETERS
73       *      NONE
74       *
75       *
76       * DESCRIPTION
77       *      Broadcasts all CVs to force re-evaluation and
78       *      new timeouts if required.
79       *
80       *      This routine may be passed directly to pthread_create()
81       *      as a new thread in order to run asynchronously.
82       *
83       *
84       * RESULTS
85       *              0               successfully broadcast all CVs
86       *              EAGAIN          Not all CVs were broadcast
87       *
88       * ------------------------------------------------------
89       */
90 {
91   int result = 0;
92   pthread_cond_t cv;
93   ptw32_mcs_local_node_t node;
94 
95   ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
96 
97   cv = ptw32_cond_list_head;
98 
99   while (cv != NULL && 0 == result)
100     {
101       result = pthread_cond_broadcast (&cv);
102       cv = cv->next;
103     }
104 
105   ptw32_mcs_lock_release(&node);
106 
107   return (void *) (size_t) (result != 0 ? EAGAIN : 0);
108 }
109