@@ -53,20 +53,32 @@ PHP_FUNCTION(uniqid)
5353 Z_PARAM_BOOL (more_entropy )
5454 ZEND_PARSE_PARAMETERS_END ();
5555
56- /* This implementation needs current microsecond to change,
57- * hence we poll time until it does. This is much faster than
58- * calling usleep(1) which may cause the kernel to schedule
59- * another process, causing a pause of around 10ms.
56+ /* This implementation needs current microsecond to change.
57+ * We will manually move the time forward if needed. This is
58+ * more stable as polling or sleeping as it will not be
59+ * effected by time changes (like ntp) and this is much faster
60+ * than calling usleep(1) which may cause the kernel to
61+ * schedule another process, causing a pause of around 10ms.
6062 */
61- do {
62- (void )gettimeofday ((struct timeval * ) & tv , (struct timezone * ) NULL );
63- } while (tv .tv_sec == prev_tv .tv_sec && tv .tv_usec == prev_tv .tv_usec );
63+ (void )gettimeofday ((struct timeval * ) & tv , (struct timezone * ) NULL );
64+ if (UNEXPECTED ((tv .tv_sec == prev_tv .tv_sec && tv .tv_usec <= prev_tv .tv_usec )
65+ || tv .tv_sec < prev_tv .tv_sec
66+ )) {
67+ prev_tv .tv_usec += 1 ;
68+ if (UNEXPECTED (prev_tv .tv_usec > 999999 )) {
69+ prev_tv .tv_sec += prev_tv .tv_usec / 1000000 ;
70+ prev_tv .tv_usec = prev_tv .tv_usec % 1000000 ;
71+ }
6472
65- prev_tv .tv_sec = tv .tv_sec ;
66- prev_tv .tv_usec = tv .tv_usec ;
73+ sec = (int ) prev_tv .tv_sec ;
74+ usec = (int ) prev_tv .tv_usec ;
75+ } else {
76+ prev_tv .tv_sec = tv .tv_sec ;
77+ prev_tv .tv_usec = tv .tv_usec ;
6778
68- sec = (int ) tv .tv_sec ;
69- usec = (int ) (tv .tv_usec % 0x100000 );
79+ sec = (int ) tv .tv_sec ;
80+ usec = (int ) (tv .tv_usec % 0x100000 );
81+ }
7082
7183 /* The max value usec can have is 0xF423F, so we use only five hex
7284 * digits for usecs.
0 commit comments