|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: O T
Length: 11709 (0x2dbd)
Types: TextFile
Names: »OS2000_INTERNALS_ASM«
└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
└─⟦77aa8350c⟧ »DATA«
└─⟦f794ecd1d⟧
└─⟦24d1ddd49⟧
└─⟦this⟧
; The use of this system is subject to the software license terms and
; conditions agreed upon between Rational and the Customer.
;
; Copyright 1988 by Rational.
;
; RESTRICTED RIGHTS LEGEND
;
; Use, duplication, or disclosure by the Government is subject to
; restrictions as set forth in subdivision (b)(3)(ii) of the Rights in
; Technical Data and Computer Software clause at 52.227-7013.
;
;
; Rational
; 3320 Scott Boulevard
; Santa Clara, California 95054-3197
;
; PROPRIETARY AND CONFIDENTIAL INFORMATION OF RATIONAL;
; USE OR COPYING WITHOUT EXPRESS WRITTEN AUTHORIZATION
; IS STRICTLY PROHIBITED. THIS MATERIAL IS PROTECTED AS
; AN UNPUBLISHED WORK UNDER THE U.S. COPYRIGHT ACT OF
; 1976. CREATED 1988. ALL RIGHTS RESERVED.
;
;
.module "OS2000_INTERNALS"
;
; Implements operations which depend on the location and
; organization of OS-9 and OS2000 internal data structures.
;
.include "^^standard_assembler_include_file"
.include "^^common.os2000_definitions"
.include "^^common.runtime_definitions"
comp_unit runtime_compunit
.sect ada_runtime_code,code,relocatable,alignment:=2
.gbl.a __get_current_task_id
.gbl.a __verify_stack
.gbl.a __fork_process
.gbl.a __current_process_id
.gbl.a __current_process_priority
.gbl.a __set_process_priority
.gbl.l __serialization.acquire_lock
.gbl.l __serialization.release_lock
.gbl.l __release_task_lock
.ext.a __process_descriptor_pointer
.ext.a __tasking_lock
.ext.a __report_fatal_error;
.ext.l __abort_main_indirect
.ext.b __abort_main_flag
;
; function Get_Current_Task_Id return Task_Id;
;
subprogram sp_rt,sp.internal,linkage.simple
__get_current_task_id:
movea.l (__process_descriptor_pointer,a5),A0
movea.l (a0),a0
move.l (art$tsk_id,a0),d0
rts
;
; function Current_Process_Id return Integer;
;
subprogram sp_rt,sp.internal,linkage.simple
__current_process_id:
moveq.l #0,d0
movea.l (__process_descriptor_pointer,a5),a0
movea.l (a0),a0
move.w (p$id,a0),d0
rts
;
; function Current_Priority return Integer;
;
subprogram sp_rt,sp.internal,linkage.simple
__current_process_priority:
statement 0,0,0
moveq.l #0,D0
movea.l (__process_descriptor_pointer,a5),a0
movea.l (a0),a0
move.w (p$prior,a0),d0
rts
;
; procedure Fork (Parameter_Ref : System.Address;
; Parameter_Size : Integer;
; Priority : Integer;
; Memory_Size : Integer;
; Result : out Status);
;
subprogram sp_rt,sp.internal,linkage.simple
__Fork_Process:
.local
$param_ref'offset equ 4+20
$param_size'offset equ 8+20
$priority'offset equ 12+20
$memory_size'offset equ 16+20
$status'offset equ 20+20
movem.l d2/d3/d4/d5/a2,-(a7)
statement 20,0,0
moveq.l #0,d0 ; module type/revision
move.l ($memory_size'offset,sp),d1 ; memory size
addi.l #runtime$stack$cushion,d1 ; add cushion to mem size
move.l ($param_size'offset,sp),d2 ; parameter size
clr.l ($status'offset,sp) ; successful status
moveq.l #4,d3 ; I/O paths
move.l ($priority'offset,sp),d4 ; priority
lea (_ada_task_module_name:16,pc),a0; module name
movea.l ($param_ref'offset,sp),a1 ; parameter address
$save_child_id:
movea.l (__process_descriptor_pointer,a5),a2
movea.l (a2),a2
move.l (p$cid,a2),d5 ; save value of child id
trap #os9_call
.dc.w f$fork
bcs.b $error
$restore_child_id:
move.l d5,(p$cid,a2) ; restore value of child id
$done: movem.l (a7)+,d2/d3/d4/d5/a2
statement 0,0,0
rts
$error: move.l d1, ($status'offset,sp) ; error status
bra.b $done
_ada_task_module_name:
.asciz "ADA_TASK"
;
; procedure Set_Priority (Process_Id : Integer; Priority : Integer);
;
subprogram sp_rt,sp.internal,linkage.simple
__Set_Process_Priority:
.local
$process_id'offset equ 4
$priority'offset equ 8
move.l ($process_id'offset,sp),d0
move.l ($priority'offset,sp),d1
trap #os9_call
.dc.w f$sprior
rtd #8
;
; function Acquire_Lock (The_Lock : Lock) return Task_Id is
; Item : Q_Element;
; begin
; Item.Key := Get_Current_Task_Id;
; if Tasking_Lock.Key = Null_Id then \
; Tasking_Lock.Key := Item.Key; \
; Tasking_Lock.Next := null; \
; return True; - Atomic
; else /
; Item.Next := Tasking_Lock.Next; /
; Tasking_Lock.Next := Item; /
;
; while Tasking_Lock.Key /= Item.Key loop
; Sleep (Some_Amount); -- awakened either by release signal
; -- or delay expiration;
; end loop;
; end if;
; end Acquire;
;
;
subprogram sp_rt,sp.internal,linkage.simple
__serialization.acquire_lock:
.local
$lock'offset equ 4+4
$allocate_size equ element'size;
move.l d3,-(SP) ; save d3
statement 0,0,1
movea.l ($lock'offset,sp),a0 ; get address of The_Lock
movea.l (__process_descriptor_pointer,a5),a1
movea.l (a1),a1
move.l (art$tsk_id,a1),d3 ; fetch current task id
move.l d3,-(SP) ; Element.Key := Get_Current_Task_Id
statement 0,0,2
subq.l #4,sp ; Element.Next uninitialized
statement 0,0,3
movea.l a0, a1 ; The_Lock'Address is in A0
addq.l #element.key,a1 ; The_Lock.Key'Address
$retry: moveq.l #0,d1
cas.l d1,d3,(a1) ; if The_Lock.Key = 0 then
; The_Lock.Key := The_Element.Key;
bne.b $failed ; if Key /= 0 then failed
$done: move.l (element.key,a0),d0 ; get The_Lock.Key
addq.l #$allocate_size,sp ; pop local queue element
statement 0,0,1
move.l (sp)+,d3 ; restore d3
statement 0,0,0
rtd #4
$failed:move.l (a0),d0 ; get The_Lock.Next
move.l d0,(sp) ; Item.Next := Lock.Next
move.l SP,d3 ; The_Element.Next'Address
cas2.l d0:d1,d3:d1,(a0):(a1) ; if Lock unchanged then
; Lock.Next := Item and
beq.b $sleep ; if equal then properly enqueued
; else concurrent interference,
move.l (Element.Key,SP),d3 ; so get The_Element.Key
bra.b $retry ; and try again to enqueue
;
; Didn't get lock, so sleep until become head of queue
; and lock is released. Don't sleep indefinitely, because
; OS-9 signals are lost (not queued) if receiver is not
; already sleeping when signal is sent. This introduces
; a race condition.
;
$sleep: move.l #-2147483644,d0 ; sleep time
trap #os9_call ; do system call
.dc.w f$sleep
move.l (element.key,a0),d0 ; get the_Lock.Key
cmp.l (element.key,sp),d0 ; compare to The_Element.Key
beq.b $done ; if equal then got the lock
bra.b $sleep ; else try again
;
; procedure Release_Task_Lock
;
subprogram sp_rt,sp.internal,linkage.simple
__release_task_lock:
btst.b #0,(__abort_main_flag,a5) ; test for main program abort
beq.b $release
movea.l (__abort_main_indirect,a5),a0
jsr (a0)
$release:
pea (__Tasking_Lock,a5) ; get address of Tasking_Lock
bsr.b __serialization.release_lock
rts
;
; procedure Release_Lock (The_Lock : Address);
;
subprogram sp_rt,sp.internal,linkage.simple
__Serialization.Release_Lock:
.local
$lock'offset equ 4
movea.l ($lock'offset,sp),a0 ; get address of The_Lock
movea.l a0,a1
addq.l #Element.Key,a1 ; Lock.Key'Address
move.l (a1),d1 ; Lock.Key
moveq.l #0,d0 ; null, null id
cas2.l d0:d1,d0:d0,(a0):(a1) ; if Lock.Next = null and
; Lock.Key = Lock.Key then
; Lock.Next := null; and
; Lock.Key := null id;
bne.b $waiters ;
rtd #4 ; released the lock, no waiters
$waiters:
movem.l d2/d3/a3,-(a7)
statement 0,0,3
$retry: movea.l d0, a3 ; Lock.Next
move.l (a3), d2 ; Lock.Next.Next
move.l (Element.Key,a3), d3 ; Lock.Next.Key
cas2.l d0:d1,d2:d3,(a0):(a1) ; if Lock unchanged then
; Lock.Next := Lock.Next.Next;
; Lock.Key := Lock.Next.Key;
bne.b $Retry ; concurrent interference
movea.l d3,a0 ; get The_Lock.Key
movem.l (a7)+,d2/d3/a3 ; restore d2, d3, and a3
statement 0,0,0
moveq.l #1,d1 ; wakeup signal
move.l (tcb.process_id,a0),d0 ; get The_Lock.Key.Process_Id
trap #os9_call ; do system call
.dc.w f$send
rtd #4
;
; procedure Verify_Stack;
;
; Verify that the current stack pointer does not
; exceed the limits for the process; if it does
; then issue an error message and die. This routine
; is called only from runtime routines which do not
; do normal stack checking, but must be able to execute
; in order to insure correct program semantics.
;
subprogram sp_rt,sp.internal,linkage.simple
__verify_stack:
.local
move.l sp,d1 ; get current stack pointer
addi.l #runtime$stack$cushion,d1 ; give back cushion for runtime
blo.s $failed ; wraps around past zero
movea.l (__process_descriptor_pointer,a5),a0
movea.l (a0),a0 ; get descriptor ptr
cmp.l (art$stk_lo,a0),d1 ; compare to low bound
blo.s $failed ; past low bound
rts
$failed:
move.l #insufficient$stack$ferror,-(sp); push fatal error value
bsr.l __report_fatal_error ; give error message
moveq.l #some$error,d0 ; return status
trap #os9_call
.dc.w f$exit
end_subprograms
.end