?? RIGHT := 110, LEFT := 1 ??
?? FMT (FORMAT := ON, keyw := upper, ident := lower) ??
?? NEWTITLE := 'MMM$SM_USER_INTERFACE' ??
MODULE mmm$sm_user_interface {MMMSMUI} ;


{
{  PURPOSE:
{     This module is used as an interface between run-anywhere
{     routines and ring 1 and monitor mem mgmnt routines.
{

?? PUSH (LISTEXT := ON) ??
*copyc GFV$NULL_SFID
*copyc MMV$CONTIGUOUS_MEM_LENGTH_MAX
*copyc MME$CONDITION_CODES
*copyc MMT$ASSIGN_CONTIG_PASS_IDENT
*copyc MMT$RB_ASSIGN_CONTIG_MEMORY
*copyc MMT$SEGMENT_DESCRIPTOR_TABLE
*copyc MMT$SEGMENT_DESCRIPTOR_TABLE_EX
*copyc OST$HEAP
*copyc OSD$VIRTUAL_ADDRESS
*copyc OST$CALLER_IDENTIFIER
*copyc OST$STATUS
*copyc OST$EXECUTION_CONTROL_BLOCK
?? POP ??


{  External procedures referenced by this module.

*copyc I#CALL_MONITOR
*copyc JSP$ADVANCE_LONG_WAIT_JOBS
*copyc MMP$VALIDATE_SEGMENT_NUMBER
*copyc MMP$ASSIGN_MASS_STORAGE
*copyc OSP$SET_STATUS_ABNORMAL
*copyc PMP$DELAY
*copyc SYP$SET_STATUS_FROM_MTR_STATUS
*copyc dmp$reallocate_file_space
*copyc mmp$validate_segment_number
*copyc syp$push_inhibit_job_recovery
*copyc syp$pop_inhibit_job_recovery
?? TITLE := 'MMP$ASSIGN_DEVICE_TO_SEGMENT' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] mmp$assign_device_to_segment (pva: ^cell;
    VAR status: ost$status);

*copy MMH$ASSIGN_DEVICE_TO_SEGMENT

    status.normal := TRUE;
    mmp$assign_mass_storage (#segment (pva), gfv$null_sfid, 0, status);

  PROCEND mmp$assign_device_to_segment;

?? TITLE := 'MMP$ASSIGN_CONTIGUOUS_MEMORY' ??
?? EJECT ??
*copyc mmh$assign_contiguous_memory

  PROCEDURE [XDCL, #GATE] mmp$assign_contiguous_memory
    (    process_virtual_address: ^cell;
         contiguous_memory_length: ost$segment_length;
     VAR status: ost$status);

     VAR
        caller_id: ost$caller_identifier,
        dummy_pages_flushed: mmt$page_frame_index,
        loop_count: 1 .. 4,
        pass_count: mmt$assign_contig_pass_ident,
        request_block: mmt$rb_assign_contig_memory,
        segment_number: ost$segment,
        sd_p: ^mmt$segment_descriptor,
        sdtx_p: ^mmt$segment_descriptor_extended;

     #CALLER_ID (caller_id);
     IF caller_id.ring > 6 THEN
       osp$set_status_abnormal ('MM', mme$ring_violation, '', status);
       RETURN;
     IFEND;

     segment_number := #SEGMENT (process_virtual_address);
     mmp$validate_segment_number (segment_number, sd_p, sdtx_p, status);
     IF NOT status.normal THEN
       RETURN;
     IFEND;

     IF (mmc$sa_wired IN sdtx_p^.software_attribute_set) OR ((mmc$sa_fixed IN
        sdtx_p^.software_attribute_set) AND (segment_number = osc$segnum_job_fixed_heap)) THEN

 {Only wired or job fixed segments are allowed.

     ELSE
       osp$set_status_abnormal ('MM', mme$contig_mem_seg_violation, '', status);
       RETURN;
     IFEND;

     IF contiguous_memory_length > mmv$contiguous_mem_length_max THEN
       osp$set_status_abnormal ('MM', mme$invalid_length_requested, '', status);
       RETURN;
     IFEND;

     request_block.request_code := syc$rc_assign_contig_memory;
     request_block.requested_length := contiguous_memory_length;
     request_block.process_virtual_address := process_virtual_address;

     FOR loop_count := 1 TO 4 DO
       pass_count := mmc$null_pass;
       REPEAT
         pass_count := SUCC (pass_count);
         CASE pass_count OF
         = mmc$scan_pft_for_free_or_avail =
           request_block.pass_count := pass_count;
         = mmc$scan_pft_free_avail_notmod =
           request_block.pass_count := pass_count;
         = mmc$scan_pft_write_mod_pages =
           request_block.pass_count := pass_count;
           i#call_monitor (#LOC (request_block), #SIZE (request_block));
           syp$set_status_from_mtr_status (request_block.status, status);
           IF NOT status.normal THEN
             RETURN;
           IFEND;
           pmp$delay (1000, status);
           request_block.pass_count := mmc$scan_pft_for_free_or_avail;
         = mmc$assign_contig_adv_long_wait =
           jsp$advance_long_wait_jobs (TRUE {flush_all_jobs}, dummy_pages_flushed);
           pmp$delay (1000, status);
           request_block.pass_count := mmc$scan_pft_for_free_or_avail;
         ELSE
         CASEND;

         i#call_monitor (#LOC (request_block), #SIZE (request_block));
         syp$set_status_from_mtr_status (request_block.status, status);
         IF ((NOT status.normal) AND (status.condition <> mme$unable_to_assign_contig_mem)) OR
             (status.normal) THEN
           RETURN;
         IFEND;
       UNTIL (pass_count = mmc$assign_contig_adv_long_wait);
       pmp$delay (1000, status);
     FOREND;

  PROCEND mmp$assign_contiguous_memory;
?? TITLE := 'MMP$REALLOCATE_FILE_SPACE' ??
?? EJECT ??
  PROCEDURE [XDCL, #GATE] mmp$reallocate_file_space
    (    pva: ^cell;
     VAR status: ost$status);

    VAR
      sd_p: ^mmt$segment_descriptor,
      sdtx_p: ^mmt$segment_descriptor_extended;

    IF pva = NIL THEN
      osp$set_status_abnormal ('MM', mme$invalid_pva, '', status);
      RETURN;
    IFEND;

    syp$push_inhibit_job_recovery;
    mmp$validate_segment_number (#segment(pva), sd_p, sdtx_p, status);
    IF NOT status.normal THEN
      syp$pop_inhibit_job_recovery;
      RETURN;
    IFEND;
    dmp$reallocate_file_space (sdtx_p^.sfid, TRUE, status);
    syp$pop_inhibit_job_recovery;

  PROCEND mmp$reallocate_file_space;
MODEND mmm$sm_user_interface
