Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Daylight saving - Repost TBO code

32 views
Skip to first unread message

Hans van Veen - ITT Gouden Gids

unread,
Oct 23, 1996, 3:00:00 AM10/23/96
to

A few weeks ago I posted a utility for changing to summer/wintertime.
Jim McKinney discovered some potential problems regarding clock cycle
lengths on an Alpha. With thanks too Jim, I hereby post the modified
code.

================================ REPOST ========================================

TBO (Time BOoster) was given to us by Digital (without any support !!!)
We use this utility on our VAXes and Alpha's without any problems sofar.

Mod's:
------
Jim McKinney discovered a bug in the source code concearning the clock cycle
length. Alpha's use a variable clock speed, and Jim modified the code to cope
with this. (Full version of his comments is attached with the code)

Thanks Jim.

--------------------------------------------------------------------------------

How to build TBO:

Underneath you find 3 files; TBO.CLD, TBO.HLP, and TBO.MAR

1. Modify the line "image 'Dev:[Dir]'TBO" in TBO.CLD to point to the
device and directory were you will put TBO.EXE.

2. If wanted put TBO.HLP in a helplibrary

3. Compile and link TBO.MAR (see header for info) and copy the image
the device and directory mentioned unde 1.


Good luck, but..... Use TBO at your own risk............

=========== Start of TBO.CLD ============== Cut Here ===========================
define verb TBO
image 'Dev:[Dir]'TBO
noparameters
qualifier RESET nonnegatable
qualifier INFO nonnegatable
qualifier DIRECTION nonnegatable, value(required, type=DIR_TYPE)
qualifier DELTA nonnegatable, value(required, type=$NUMBER)
qualifier RANGE nonnegatable, value(required, type=$NUMBER)

disallow RESET and (DELTA or RANGE or DIRECTION)
disallow DELTA and not (RANGE and DIRECTION)
disallow RANGE and not (DELTA and DIRECTION)
disallow DIRECTION and not (DELTA and RANGE)

define type DIR_TYPE
keyword BACKWARD
keyword FORWARD
============= End of TBO.CLD ============== Cut Here ===========================


=========== Start of TBO.HLP ============== Cut Here ===========================
1 TBO

TBO (Time Booster) is a OpenVMS VAX and AXP utility which allows
privileged users to gradualy move the OpenVMS time back- or forwards.
This utility is ment to be used when switching from summer- to
wintertime or vica versa.


Supplied by Digital without support !!!!


Syntax:

$ TBO /Qualifiers


2 Parameter

TBO has no parameters


2 Example

$ TBO /INFO
%TBO-I-IDENT, VAX/VMS Time Booster Rev 1.0
%TBO-I-INFO, Systemtime: 2-APR-1996 10:28:05.58
Timeadjust: 0
Ticklength: 9765

$ TBO /DIRECTION=BACKWARD /RANGE=14400 /DELTA=3600 /INFO
%TBO-I-IDENT, VAX/VMS Time Booster Rev 1.0
%TBO-I-INFO, Systemtime: 2-APR-1996 10:29:34.30
Timeadjust: 14745600
Ticklength: 7323

This command will move the clock 1 hour back over a period of
4 hours (summertime -> wintertime). /INFO will display the
current time, the adjustment duration, and the reduced ticklength.

Subsequent TBO /INFO commands will display the TBO progress (i.e.
the Timeadjust value will reduce slowly to zero).

Once TBO is active it can be stopped using the TBO /RESET command.

$ TBO /RESET /INFO
%TBO-I-IDENT, VAX/VMS Time Booster Rev 1.0
%TBO-I-RESET, Default ticklength restored
%TBO-I-INFO, Systemtime: 2-APR-1996 10:34:17.57
Timeadjust: 0
Ticklength: 9765


2 /DIRECTION

Format:

TBO /DIRECTION=Keyword /RANGE=Number /DELTA=Number [/INFO]

/DIRECTION is used to specify whether the time adjustment is made
for summertime (/DIRECTION=FORWARD) or for wintertime (/DIRECTION=
BACKWARD).

This qualifier must be used together with /DELTA and /RANGE, /INFO
is optional.


2 /RANGE

Format:

TBO /DIRECTION=Keyword /RANGE=Number /DELTA=Number [/INFO]

/RANGE is used to specify the adjustment duration in seconds.
So /RANGE=14400 specifies a 4 hour period during which the
clock will be adjusted in the specified direction.

This qualifier must be used together with /DIRECTION and
/DELTA, /INFO is optional.


2 /DELTA

Format:

TBO /DIRECTION=Keyword /RANGE=Number /DELTA=Number [/INFO]

/DELTA is used to specify the number of seconds the clock has to
be adjusted. So /DELTA=3600 is used to move the clock 1 hour back-
or forward (depends on the value of /DIRECTION). The duration of
the adjustment is specified by /RANGE.

This qualifier must be used together with /DIRECTION and
/RANGE, /INFO is optional.


2 /RESET

Format:

TBO /RESET

This command (no other qualifiers, except /INFO, are allowed) resets
the clock update action. Whenever a TBO command is issued to change
the time, 2 internal OpenVMS memory locations (EXE$GL_TICKLENGTH and
EXE$GL_TIMEADJUST) are modified. /RESET forces the original values
into the memory locations, therby stopping the adjustment action.


2 /INFO

Format:

TBO /INFO

Using /INFO will display the current system time, and the contents
of the locations EXE$GL_TICKLENGTH and EXE$GL_TIMEADJUST. The first
memory location specifies the number of hardware clock ticks which
make up a 10 msec unit, the 2nd location specifies the number of
hardware clockticks which have to pass before the 1st loctaion is
reseted to it's original value.

============= End of TBO.CLD ============== Cut Here ===========================


Jim McKinney's comments and suggestions on TBO
----------------------------------------------

From: ITTPUB::IN%"mcki...@cpva.saic.com" 4-OCT-1996 21:24:07.59
To: ve...@nl101.ittpub.nl
CC:
Subj: RE: [Macro Code]: How to change time backwards?

From cpva.saic.com!MCKINNEYJ Fri Oct 4 20:37:58 1996 remote from sun4nl
Received: from sun4nl by ittpub.nl (DECUS UUCP ///1.3-1/2.5/);
Fri, 4 Oct 96 21:24:10 WET
Received: from cpmx.mail.saic.com by sun4nl.NL.net (5.65b/NLnet-3.4)
id AA29174; Fri, 4 Oct 1996 20:37:58 +0200
Return-Path: <MCKI...@cpva.saic.com>
Received: from cpva.saic.com by cpmx.mail.saic.com; Fri, 4 Oct 96 11:37:49 -0700
Date: Fri, 4 Oct 1996 11:36:43 -0700 (PDT)
From: MCKI...@cpva.saic.com
To: ve...@nl101.ittpub.nl
Message-Id: <9610041136...@cpva.saic.com>
Subject: RE: [Macro Code]: How to change time backwards?

Hans -
You posted some code on 15-Aug-1996... TBO. It's a slick little utility;

>X-News: cpgtsa comp.os.vms:124161
>From: ve...@nl101.ittpub.nl (Hans van Veen - ITT Gouden Gids)
>Subject:[Macro Code]: How to change time backwards?
>Date: 15 Aug 96 12:00:19 WET+0100
>Message-ID:<1996Aug15.120019@ittpub>

however, it has a dependency on the clock cycle of the VAX and gives
incorrect results on Alphas. It will not compute the Timeadjust period
correctly since the Alpha's clock cycle is different than the VAX's.
You can check this out by issueing the TBO command for some RANGE
(perhaps an hour) and specifying a 0 value for the DELTA. If you time
it with your watch you'll see that it isn't an hour (but on the VAX it
is). Try a command like TBO/DIRE=FORW/RANGE=3600/DELT=0/INFO. For an
Alpha (with a clock cycle of 1024) you would expect a Timeadjust value
reported back of 3686400 (1024cycles*60min*60sec). I've modified the
code to (I believe) handle the Alpha's potentially variable clock speed
and have attached the code below. Check it out and see what you think.
Look for the string "ALPHA" in the code to see all the modifications,
as I've implemented them all as "ifdefs". If you agree, then perhaps
you should post the updated version to comp.os.vms (or infovax) for
those that have Alphas. Anyway, let me know what you think.
- Jim
--
Jim McKinney: mcki...@cpva.saic.com | (619)458-2075 | SAIC, Campus Point

=========== Start of TBO.MAR ============== Cut Here ===========================

.title Time_Booster
.ident "Version 2.0"

; VAX has a 10millisecond clock (a tick). ALPHA has an interval timer that
; is determined by the value in the hardware restart parameter block (HWRPB)
; at offset HWRPB$IQ_CLOCK_INT_FREQ. This value will minimally be 1000 and
; and initially all ALPHA systems will generate 1024 interupts (ticks) per
; second.
;
; Note that we'll use the following:
; VAX & ALPHA:
; EXE$GL_SYSTICK - standard clock tick length
; EXE$GL_TICKLENGTH - increment added to clock at each hardware clock interrupt
; EXE$GL_TIMEADJUST - number of ticks to apply EXE$GL_TICKLENGTH
; ALPHA:
; EXE$GPL_HWRPB_L - hardware restart parameter block
; HWRPB$IL_CLOCK_FREQ_L - offset to clock interrupt frequency

;
; define ALPHA if R22 is a register and not a symbol
;
.ntype ...IS_IT_ALPHA,r22 ;Get the type of R22
...IS_IT_ALPHA = <...IS_IT_ALPHA@-4&^XF>-5
.iif eq,...IS_IT_ALPHA, ALPHA=1

.library "sys$share:lib.mlb"
.if not_defined, ALPHA ; VAX only
.link "sys$system:sys.stb" /selective_search
.endc ; AXP use LINK/SYSEXE=SELECTIVE

$clidef ; CLI codes
.if defined, ALPHA
$hwrpbdef ; hardware codes
.endc
$ssdef ; system service status codes

.macro test_ret ?l
blbs r0,l
$exit_s r0
l:
.endm test_ret

.psect string, noexe, nowrt, quad
ann: .ascid "%TBO-I-IDENT, OpenVMS Time Booster Rev 2.0"
res_ann: .ascid "%TBO-I-RESET, Default ticklength restored"
cntr_info: .ascid "%TBO-I-INFO, Systemtime: !AS!/ Timeadjust: !UL!/ Ticklength: !UL"
noalq: .ascid "%TBO-E-NOTALLQUAL, Not all qualifiers are specified"
res_entity: .ascid "reset"
inf_entity: .ascid "info"
del_entity: .ascid "delta"
rang_entity: .ascid "range"
dir_entity: .ascid "direction"
dir_det: .ascii "B"
.align long
addend: .long 0

.page
.psect data, noexe, wrt, quad
lock_adr: .address lock_start
.address lock_end
deflen: .blkl 1
numargs: .long 0
direc_s: .long 1 ; Direction is forward
range_s: .long 0
delta_s: .long 0
ticklength: .blkl 1
timeadjust: .blkl 1
.if defined, ALPHA
clockfreq: .blkl 1
.endc
systick: .blkl 1
remainder: .blkl 1
multipl: .blkl 1
.align quad
product: .blkq 1
systime: .blkq 1
systime$: .ascid "xx-xxx-xxxx xx:xx:xx.xx"
.align long
out_desc: .long 132
.address faobuf
faobuf: .blkb 132
.align long
cvt_desc: .word 8
.word 270
.address cvtbuf
cvtbuf: .blkb 8

.page
.psect code, exe, nowrt, quad

.entry main,^m<>
pushal ann ; Push descriptor address
calls #1,g^lib$put_output ; Let every one whats running
$lkwset_s inadr=lock_adr ; Lock the privileged code in the working set
test_ret ; Check the return value
pushal res_entity
calls #1,g^cli$present ; Do we want to reset?
cmpl r0,#cli$_present ; If option is reset then
bneq 10$
$cmkrnl_s routin=reset_hwclk ; Initiate reset routine
test_ret ; Check the return value
pushal res_ann ; Push success message
calls #1,g^lib$put_output ; Cry it out!
brw 20$
10$: bsbw scan_cli ; See if there is something to mess around whith?
tstl numargs ; No qualifiers?
beql 20$ ; Then there is only one item to check left.
cmpl #3, numargs ; Are there three items
beql 22$ ; If not, then exit
pushal noalq
calls #1,g^lib$put_output
brb 30$
22$: bsbw calc_ticks ; Calculate needed correction
20$: pushal inf_entity
calls #1,g^cli$present ; Do we want info?
cmpl r0,#cli$_present ; If option is info then
bneq 30$
bsbw hwclk_info ; try to find out the current settings
30$: $exit_s ; Initiate image rundown
ret

hwclk_info: .iif defined, ALPHA, .jsb_entry
$cmkrnl_s routin=copy_info
test_ret ; Check the return value
$asctim_s timlen=deflen, - ; Convert quad word to system time string
timbuf=systime$, -
timadr=systime, -
cvtflg=#0
$fao_s ctrstr=cntr_info, - ; Make everything readable and
outbuf=out_desc, - ; store it in a buffer
p1=#systime$, -
p2=timeadjust, -
p3=ticklength
pushal out_desc
calls #1,g^lib$put_output ; Cry it out!
rsb

scan_cli: .iif defined, ALPHA, .jsb_entry output=r0, preserve=r1
clrl numargs
pushal dir_entity
calls #1,g^cli$present ; Test the precense of the direction qualifier
cmpl r0,#cli$_present ; Which way do we want to travel?
bneq 110$ ; No direction?!, check the user for another errors!
incl numargs ; Increment the parameter counter
pushal cvt_desc
pushal dir_entity
calls #2,g^cli$get_value ; Return the value assigned to the qualifier
moval cvtbuf,r1
cmpb dir_det,(r1) ; If direction is backward
bneq 110$
movl #-1,direc_s ; Direc_s is negative
110$: pushal del_entity ; Check next entity
calls #1,g^cli$present ; Test the presence of the delta qualifier
cmpl r0,#cli$_present ; How many seconds are involved
bneq 115$ ; And no delta? What are we doing?
incl numargs
movl #8,cvt_desc ; Restore buffer size
pushal cvt_desc ; Let the return value set up the descriptor
pushal cvt_desc
pushal del_entity
calls #3,g^cli$get_value ; Return the delta value
pushal delta_s
pushal cvt_desc
calls #2,g^ots$cvt_tu_l ; Convert delta string to unsigned long word
test_ret
115$: pushal rang_entity ; Check next entity
calls #1,g^cli$present ; Test the presence of the range qualifier
cmpl r0,#cli$_present ; How many seconds are involved
bneq 120$ ; Even no range, we better exit this routine
incl numargs
movl #8,cvt_desc ; Restore buffer size
pushal cvt_desc ; Let the return value set up the descriptor
pushal cvt_desc
pushal rang_entity
calls #3,g^cli$get_value ; Return the range value
pushal range_s
pushal cvt_desc
calls #2,g^ots$cvt_tu_l ; Convert delta string to unsigned long word
test_ret
120$: movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl
rsb


calc_ticks: .iif defined, ALPHA, .jsb_entry preserve=<r1,r2,r3,r4,r5>
$cmkrnl_s routin=get_systick ; Retrieve systick
.if defined, ALPHA ; If AXP Derive the clock resolution
movl clockfreq,r1 ;; Load ticks per second
movl systick,r3 ;; Load standard clock tick length
mull2 r3,r1 ;; Formula: (freq*systick)
.iff ; Else
movl #10000000,r1 ; If VAX Load clock resolution (1/100ns)
.endc
movl range_s,r2 ; Load range in seconds
movl systick,r3 ; Load exe$gl_systick
divl2 r3,r1 ; r1 contains number of ticks required to adjust time
mull2 r2,r1 ; Formula: (1E7*range/systick)
movl r1,timeadjust ; Save it

movl delta_s,r4 ; Load delta value
movl direc_s,r5 ; Load direction
mull2 r5,r4 ; Calc direction
addl2 r2,r4
movl r4,multipl ; Store r4
pushal product ; Push the arguments
pushal addend
pushal systick
pushal multipl
calls #4,g^lib$emul ; Perform a 64 bit multiplication
pushal remainder
pushal ticklength
pushal product
pushal range_s
calls #4,g^lib$ediv ; Formula: ((range+(delta*direc))*systick/range) => new ticklength
$cmkrnl_s routin=store_ticks ; Store calculated values in hwclk data structures
rsb


.page
.psect prcode, exe, nowrt ; This psect contains code which runs at an elevated ipl
.if defined, ALPHA
.call_entry max_args=0,home_args=false,label=reset_hwclk,output=r0
.iff
.entry reset_hwclk,^m<>
.endc
lock_start: ; and is locked in the working set
lock lockname=hwclk ; Lock hardware clock data structures
clrl g^exe$gl_timeadjust ; Disable clock adjustment
movl g^exe$gl_systick,g^exe$gl_ticklength ; Restore standard tick
unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock
movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl
ret


.if defined, ALPHA
.call_entry max_args=0,home_args=false,label=copy_info,output=r0
.iff
.entry copy_info,^m<>
.endc
lock lockname=hwclk ; Lock hardware clock data structures
movl g^exe$gl_timeadjust, timeadjust ; Save timeadjust value in order to release lock as quick as possible
movl g^exe$gl_ticklength, ticklength ; Do the same with the ticklength value
movq g^exe$gq_systime, systime ; Even system time is saved for whatever the purpose may be
unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock
movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl
ret


.if defined, ALPHA
.call_entry max_args=0,home_args=false,label=get_systick,output=r0
.iff
.entry get_systick,^m<>
.endc
lock lockname=hwclk ; Lock hardware clock data structures
movl g^exe$gl_systick,systick ; Copy systick value
.if defined, ALPHA ; Copy clock interrupt frequency
; and adjust for it's scaling
; the clock interrupt frequency rate is given to the system in the
; HWRPB. The value is a scaled up value (*4096) of the real ticks
; per second value.
; (VMS Source Listings - [V62.SYS.LIS]TIMESCHDL_MIN.LIS)
movl exe$gpl_hwrpb_l, r0
ashl #-12, hwrpb$il_clock_int_freq_l(r0), clockfreq
.endc
unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock
movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl
ret


.if defined, ALPHA
.call_entry max_args=0,home_args=false,label=store_ticks,output=r0
.iff
.entry store_ticks,^m<>
.endc
lock lockname=hwclk ; Lock hardware clock data structures
movl timeadjust, g^exe$gl_timeadjust ; Store timeadjust value
movl ticklength, g^exe$gl_ticklength ; Store new ticklength value
unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock
movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl
ret
lock_end:
.end main

============= End of TBO.MAR ============== Cut Here ===========================

--

Cheers, Hans

Hans van Veen Email : hvv...@goudengids.nl
ITT Gouden Gids IS/OS ha...@ittpub.nl
Hoekenrode 1 Phone : +31 (0)20 5676797
1102 BR AMSTERDAM, Netherlands Fax : +31 (0)20 6965480


Dave Pickles

unread,
Oct 30, 1996, 3:00:00 AM10/30/96
to

In article: <1996Oct23.091504@ittpub> ve...@nl101.ittpub.nl (Hans van Veen -
ITT Gouden Gids) writes:
>
> A few weeks ago I posted a utility for changing to summer/wintertime.
> Jim McKinney discovered some potential problems regarding clock cycle
> lengths on an Alpha. With thanks too Jim, I hereby post the modified
> code.

<code snipped>

Thanks for this excellent utility!

One small problem; the program modifies the time on the running system but not
the time-of-year clock or the value in the boot image. Doing a SYSMAN SET
CONFIG TIME across the cluster restores the old time from the t-o-y! Is there
any simple way round this, other than a $GETIME followed by $SETTIM?
--
Dave Pickles


GWDVMS::MOELLER

unread,
Oct 31, 1996, 3:00:00 AM10/31/96
to

Dave Pickles <da...@NUGATE.DEMON.CO.UK> writes:
>[...]

> One small problem; the program modifies the time on the running system but not
> the time-of-year clock or the value in the boot image. Doing a SYSMAN SET
> CONFIG TIME across the cluster restores the old time from the t-o-y! Is there
> any simple way round this, other than a $GETIME followed by $SETTIM?

A pretty good approximation can be had at DCL level:

$ set time=-0:0:0.0

(that's a not a delta time but a combination time,
as CJL has pointed out so often :-).

The classic solution,
$ set time="''f$time'"
as used in e.g. SHUTDOWN.COM, causes an image activation
between $GETTIM & $SETIME, and therefore tends to lose a
few clock ticks.

BTW, in order to appreciate the difference,
you need a good reference clock, like e.g. NTP
or DNETDATE.COM which I posted some time ago.

Wolfgang J. Moeller, Tel. +49 551 2011516 or -510, moe...@gwdvms.dnet.gwdg.de
GWDG, D-37077 Goettingen, F.R.Germany | Disclaimer: No claim intended!
<moe...@decus.decus.de> ----- <moe...@gwdg.de> ----- <w.mo...@ieee.org>

0 new messages