www.delorie.com/djgpp/bugs/show.cgi   search  
Bug 000295

When Created: 07/24/1999 19:00:30
Against DJGPP version: 2.02
By whom: steve@effectivejava.com
Abstract: uclock returns negative values
uclock() occasionally return negative values. The following program can either produce a series of increasing positive values or a mix of negative and positive values:

  #include <iostream.h>
  #include <time.h>

  int main()
  {
      for (int i = 0; i < 10; ++i)
          cout << uclock() << "\n";
  }

Running it might produce this output:

  0
  7103
  7664
  8028
  8385
  8741
  9096
  9451
  9806
  10162

or a series of values like this:

  0
  2093
  4037
  -58070
  -56036
  -54057
  -52130
  -50167
  -48190
  -46209

I noticed that there is a closed bug that has something to do with this. It seemed to revolve around using an out-dated RTC chip. My motherboard is less than six months old.

P.S. Is it possible for you to let me know by email if you are able to reproduce this?

P.P.S. I love DJGPP. It's made my (DOS) programming life much more enjoyable! We were using Watcom before we ported to DJGPP (I wouldn't wish that horrid compiler on my worst enemy).

Note added: 07/30/1999 03:00:46
By whom: eliz@is.elta.co.il
It seems that Windows takes its time before the reprogramming of the
timer takes effect.  The solution is to wait for one timer tick after
the initial reprogramming.  See the patch in the solution part.

Solution added: 07/30/1999 03:00:46
By whom: eliz@is.elta.co.il
This problem is solved in WIP and will be fixed in v2.03.  In the meantime,
apply the following patch:


*** src/libc/pc_hw/timer/uclock.c.~1~     Fri Jan 26 04:39:06 1996        
--- src/libc/pc_hw/timer/uclock.c Wed May 19 11:00:18 1999                
***************                                                                 
*** 1,9 ****                                                                    
--- 1,11 ----                                                                   
  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */               
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */               
  #include <time.h>                                                             
+ #include <errno.h>                                                            
  #include <pc.h>                                                               
  #include <libc/farptrgs.h>                                                    
  #include <go32.h>                                                             
+ #include <dpmi.h>                                                             
  #include <libc/bss.h>                                                         
                                                                                
  static int uclock_bss = -1;                                                   
***************                                                                 
*** 26,31 ****                                                                  
--- 28,35 ----                                                                  
                                                                                
    if (uclock_bss != __bss_count)                                              
    {                                                                           
+     int e = errno;                                                            
+                                                                               
      /* switch the timer to mode 2 (rate generator) */                         
      /* rather than mode 3 (square wave), which doesn't count linearly. */     
                                                                                
***************                                                                 
*** 36,41 ****                                                                  
--- 40,60 ----                                                                  
      base = 0;                                                                 
      last_tics = 0;                                                            
      uclock_bss = __bss_count;                                                 
+                                                                               
+     /* It seems like Windows 9X virtualization of the timer device            
+        delays the actual execution of the above command until the             
+        next timer tick.  Or maybe it only consults the actual device          
+        once per tick.  In any case, the values returned during the            
+        first 55 msec after the timer was reprogrammed still look as           
+        if the timer worked in mode 3.  So we simply wait for one clock        
+        tick when we run on Windows.  */                                       
+     _farsetsel(_dos_ds);                                                      
+     otics = _farnspeekl(0x46c);                                               
+     do {                                                                      
+       errno = 0;                                                              
+       __dpmi_yield(); /* will set errno to ENOSYS on plain DOS */             
+     } while (errno == 0 && _farnspeekl(0x46c) == otics);                      
+     errno = e;                                                                
    }                                                                           
                                                                                
    /* Make sure the numbers we get are consistent */

Fixed in version on 07/30/1999 03:00:49
By whom: eliz@is.elta.co.il



  webmaster     delorie software   privacy  
  Copyright © 2010   by DJ Delorie     Updated Jul 2010