@@ -49,21 +49,18 @@ lock_dealloc(lockobject *self)
4949 * timeout.
5050 */
5151static PyLockStatus
52- acquire_timed (PyThread_type_lock lock , PY_TIMEOUT_T microseconds )
52+ acquire_timed (PyThread_type_lock lock , _PyTime_t timeout )
5353{
5454 PyLockStatus r ;
55- _PyTime_timeval curtime ;
56- _PyTime_timeval endtime ;
57-
58-
59- if (microseconds > 0 ) {
60- _PyTime_monotonic (& endtime );
61- endtime .tv_sec += microseconds / (1000 * 1000 );
62- endtime .tv_usec += microseconds % (1000 * 1000 );
63- }
55+ _PyTime_t endtime = 0 ;
56+ _PyTime_t microseconds ;
6457
58+ if (timeout > 0 )
59+ endtime = _PyTime_GetMonotonicClock () + timeout ;
6560
6661 do {
62+ microseconds = _PyTime_AsMicroseconds (timeout , _PyTime_ROUND_UP );
63+
6764 /* first a simple non-blocking try without releasing the GIL */
6865 r = PyThread_acquire_lock_timed (lock , 0 , 0 );
6966 if (r == PY_LOCK_FAILURE && microseconds != 0 ) {
@@ -82,14 +79,12 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
8279
8380 /* If we're using a timeout, recompute the timeout after processing
8481 * signals, since those can take time. */
85- if (microseconds > 0 ) {
86- _PyTime_monotonic (& curtime );
87- microseconds = ((endtime .tv_sec - curtime .tv_sec ) * 1000000 +
88- (endtime .tv_usec - curtime .tv_usec ));
82+ if (timeout > 0 ) {
83+ timeout = endtime - _PyTime_GetMonotonicClock ();
8984
9085 /* Check for negative values, since those mean block forever.
9186 */
92- if (microseconds <= 0 ) {
87+ if (timeout <= 0 ) {
9388 r = PY_LOCK_FAILURE ;
9489 }
9590 }
@@ -99,44 +94,60 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
9994 return r ;
10095}
10196
102- static PyObject *
103- lock_PyThread_acquire_lock (lockobject * self , PyObject * args , PyObject * kwds )
97+ static int
98+ lock_acquire_parse_args (PyObject * args , PyObject * kwds ,
99+ _PyTime_t * timeout )
104100{
105101 char * kwlist [] = {"blocking" , "timeout" , NULL };
106102 int blocking = 1 ;
107- double timeout = -1 ;
108- PY_TIMEOUT_T microseconds ;
109- PyLockStatus r ;
103+ PyObject * timeout_obj = NULL ;
104+ const _PyTime_t unset_timeout = _PyTime_FromNanoseconds (-1000000000 );
110105
111- if (!PyArg_ParseTupleAndKeywords (args , kwds , "|id:acquire" , kwlist ,
112- & blocking , & timeout ))
113- return NULL ;
106+ * timeout = unset_timeout ;
114107
115- if (!blocking && timeout != -1 ) {
116- PyErr_SetString (PyExc_ValueError , "can't specify a timeout "
117- "for a non-blocking call" );
118- return NULL ;
108+ if (!PyArg_ParseTupleAndKeywords (args , kwds , "|iO:acquire" , kwlist ,
109+ & blocking , & timeout_obj ))
110+ return -1 ;
111+
112+ if (timeout_obj
113+ && _PyTime_FromSecondsObject (timeout , timeout_obj , _PyTime_ROUND_UP ) < 0 )
114+ return -1 ;
115+
116+ if (!blocking && * timeout != unset_timeout ) {
117+ PyErr_SetString (PyExc_ValueError ,
118+ "can't specify a timeout for a non-blocking call" );
119+ return -1 ;
119120 }
120- if (timeout < 0 && timeout != -1 ) {
121- PyErr_SetString (PyExc_ValueError , "timeout value must be "
122- "strictly positive" );
123- return NULL ;
121+ if (* timeout < 0 && * timeout != unset_timeout ) {
122+ PyErr_SetString (PyExc_ValueError ,
123+ "timeout value must be positive" );
124+ return -1 ;
124125 }
125126 if (!blocking )
126- microseconds = 0 ;
127- else if (timeout == -1 )
128- microseconds = -1 ;
129- else {
130- timeout *= 1e6 ;
131- if (timeout >= ( double ) PY_TIMEOUT_MAX ) {
127+ * timeout = 0 ;
128+ else if (* timeout != unset_timeout ) {
129+ _PyTime_t microseconds ;
130+
131+ microseconds = _PyTime_AsMicroseconds ( * timeout , _PyTime_ROUND_UP ) ;
132+ if (microseconds >= PY_TIMEOUT_MAX ) {
132133 PyErr_SetString (PyExc_OverflowError ,
133134 "timeout value is too large" );
134- return NULL ;
135+ return -1 ;
135136 }
136- microseconds = (PY_TIMEOUT_T ) timeout ;
137137 }
138+ return 0 ;
139+ }
140+
141+ static PyObject *
142+ lock_PyThread_acquire_lock (lockobject * self , PyObject * args , PyObject * kwds )
143+ {
144+ _PyTime_t timeout ;
145+ PyLockStatus r ;
138146
139- r = acquire_timed (self -> lock_lock , microseconds );
147+ if (lock_acquire_parse_args (args , kwds , & timeout ) < 0 )
148+ return NULL ;
149+
150+ r = acquire_timed (self -> lock_lock , timeout );
140151 if (r == PY_LOCK_INTR ) {
141152 return NULL ;
142153 }
@@ -281,41 +292,13 @@ rlock_dealloc(rlockobject *self)
281292static PyObject *
282293rlock_acquire (rlockobject * self , PyObject * args , PyObject * kwds )
283294{
284- char * kwlist [] = {"blocking" , "timeout" , NULL };
285- int blocking = 1 ;
286- double timeout = -1 ;
287- PY_TIMEOUT_T microseconds ;
295+ _PyTime_t timeout ;
288296 long tid ;
289297 PyLockStatus r = PY_LOCK_ACQUIRED ;
290298
291- if (!PyArg_ParseTupleAndKeywords (args , kwds , "|id:acquire" , kwlist ,
292- & blocking , & timeout ))
299+ if (lock_acquire_parse_args (args , kwds , & timeout ) < 0 )
293300 return NULL ;
294301
295- if (!blocking && timeout != -1 ) {
296- PyErr_SetString (PyExc_ValueError , "can't specify a timeout "
297- "for a non-blocking call" );
298- return NULL ;
299- }
300- if (timeout < 0 && timeout != -1 ) {
301- PyErr_SetString (PyExc_ValueError , "timeout value must be "
302- "strictly positive" );
303- return NULL ;
304- }
305- if (!blocking )
306- microseconds = 0 ;
307- else if (timeout == -1 )
308- microseconds = -1 ;
309- else {
310- timeout *= 1e6 ;
311- if (timeout >= (double ) PY_TIMEOUT_MAX ) {
312- PyErr_SetString (PyExc_OverflowError ,
313- "timeout value is too large" );
314- return NULL ;
315- }
316- microseconds = (PY_TIMEOUT_T ) timeout ;
317- }
318-
319302 tid = PyThread_get_thread_ident ();
320303 if (self -> rlock_count > 0 && tid == self -> rlock_owner ) {
321304 unsigned long count = self -> rlock_count + 1 ;
@@ -327,7 +310,7 @@ rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
327310 self -> rlock_count = count ;
328311 Py_RETURN_TRUE ;
329312 }
330- r = acquire_timed (self -> rlock_lock , microseconds );
313+ r = acquire_timed (self -> rlock_lock , timeout );
331314 if (r == PY_LOCK_ACQUIRED ) {
332315 assert (self -> rlock_count == 0 );
333316 self -> rlock_owner = tid ;
@@ -1362,7 +1345,9 @@ static struct PyModuleDef threadmodule = {
13621345PyMODINIT_FUNC
13631346PyInit__thread (void )
13641347{
1365- PyObject * m , * d , * timeout_max ;
1348+ PyObject * m , * d , * v ;
1349+ double time_max ;
1350+ double timeout_max ;
13661351
13671352 /* Initialize types: */
13681353 if (PyType_Ready (& localdummytype ) < 0 )
@@ -1379,10 +1364,14 @@ PyInit__thread(void)
13791364 if (m == NULL )
13801365 return NULL ;
13811366
1382- timeout_max = PyFloat_FromDouble (PY_TIMEOUT_MAX / 1000000 );
1383- if (!timeout_max )
1367+ timeout_max = PY_TIMEOUT_MAX / 1000000 ;
1368+ time_max = floor (_PyTime_AsSecondsDouble (_PyTime_MAX ));
1369+ timeout_max = Py_MIN (timeout_max , time_max );
1370+
1371+ v = PyFloat_FromDouble (timeout_max );
1372+ if (!v )
13841373 return NULL ;
1385- if (PyModule_AddObject (m , "TIMEOUT_MAX" , timeout_max ) < 0 )
1374+ if (PyModule_AddObject (m , "TIMEOUT_MAX" , v ) < 0 )
13861375 return NULL ;
13871376
13881377 /* Add a symbolic constant */
0 commit comments