.title dispatch .library /sys$library:lib/ .library /tachyon_common:tachyon_common/ ; This module is a dispatcher for a privileged shareable image. In addition ; to the dispatcher itself, transfer vectors for kernel, executive, and user ; mode routines may be defined here. The actual routines may also be defined ; here. If the routines are in another module, the "external" argument may be ; used on the system service definition. ; The library_vector_block macro sets up all of the macros needed for the ; dispatcher. Every kernel and executive system service must have a number ; assigned to it. This number is used in the CHMK or CHME instruction to invoke ; the system service. The kernel_base and executive_base parameters are the ; starting numbers for the services in this privileged shareable image. ; Note: every privileged shareable image should have DIFFERENT starting ; numbers. If a process maps two different privileged shareable images with ; overlapping system service numbers, the services of the image activated last ; can't be used. User-written system services should always have negative ; numbers, to avoid conflicts with the VMS standard system services. It ; doesn't hurt if there is overlap between kernel and executive mode service ; numbers, because the two ranges are independent. library_vector_block kernel_base=-20000 executive_base=-20000,- rundown=my_rundown ; A pair of system services, lock_pages, and unlock_pages, are built into the ; dispatcher. Since some services execute at high IPL, such as the one ; immediately following, they must be locked into memory. A page fault at IPL ; greater than two will crash the system. A call to lock_pages (no parameters ; needed) will lock all pages in the psect $lockcode (and therefore all ; internal services with lock=yes) into the working set. The code of all ; external services that execute at high IPL should also be in $lockcode. ; The get_system_time routine copies EXE$GQ_SYSTIME and the time of the first ; TQE, EXE$GQ_1ST_TIME, into quadwords supplied by the caller. The HWCLK spin ; lock must be acquired before accessing these fields. ; This routine is completely defined here, so both the transfer vector and the ; ".entry" are generated within the macro. kernel_system_service get_system_time,2,mask=<<^m<>>>,lock=yes ifnowrt #8,@4(ap),55$ ; check parameter 1 for write access ifnowrt #8,@8(ap),55$ ; check parameter 2 for write access lock_pages_if_necessary ; lock this code into the working set lock hwclk ; acquire hardware clock spinlock movq g^exe$gq_systime,@4(ap) ; get system time movq g^exe$gq_1st_time,@8(ap) ; get time of first tqe unlock hwclk ; release hardware clock spinlock movl #ss$_normal,r0 ; set normal completion status ret 55$: brw kernel_accvio ; indicate access violation ; Here we have some kernel routines declared externally. Obviously the code ; for these routines exists in some other module. These external routines may ; be written in macro, or they may be written in a high-level language. For ; external routines, only the transfer vector is generated by the macro. ; get_ucb_from_channel_number(channel_number,ucb) kernel_system_service get_data_from_channel_number,5,external=yes ; get_my_pcb_address(pcb) kernel_system_service get_my_pcb_address,1,external=yes ; get_my_phd_address(phd) kernel_system_service get_my_phd_address,1,external=yes ; Here we provide an image rundown handler. This one unlocks the pages that ; were locked into the working set for the high-IPL code. Of course, the pages ; will be deleted by image rundown anyway. Rundown handlers are called by ; JSB and therefore must be in macro. However, this routine could be a ; jacket routine that does nothing more than a regular CALLS to a procedure ; written in a high-level language. If a rundown handler is supplied, it must ; be specified on the library_vector_block macro. my_rundown:: unlock_locked_pages rsb ; This rundown routine does nothing more than unlock the high-IPL pages we ; locked earlier. This isn't really necessary. because rundown of the image ; will get rid of the pages entirely, but it doesn't hurt anything. ; Now we generate the code of the actual change-mode dispatchers. This should ; be the last line of the dispatcher module (or should at least follow all ; the system service definitions). generate_dispatchers .end