DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ O T

⟦98babe9bd⟧ TextFile

    Length: 11709 (0x2dbd)
    Types: TextFile
    Names: »OS2000_INTERNALS_ASM«

Derivation

└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
    └─ ⟦77aa8350c⟧ »DATA« 
        └─⟦f794ecd1d⟧ 
            └─⟦24d1ddd49⟧ 
                └─⟦this⟧ 

TextFile

;    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