?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE MEMORY MANAGEMENT - RING1 HELPER ROUTINES' ??
MODULE mmm$ring1_helper;

{ PURPOSE:
{   This module contains memory manager procedures that run in ring 1 task services.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$mainframe_paged_literal
*copyc mme$condition_codes
*copyc mmt$manage_memory_utility
*copyc mmt$page_frame_queue_id
*copyc mmt$page_q_counts
?? POP ??
*copyc clp$convert_integer_to_rjstring
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc jmv$ijl_p
*copyc mmv$age_interval_ceiling
*copyc mmv$age_interval_floor
*copyc mmv$aggressive_aging_level
*copyc mmv$aging_algorithm
*copyc mmv$avail_mod_q_decr_per_task
*copyc mmv$avail_mod_q_floor_min
*copyc mmv$avail_mod_waitq_dequeue_int
*copyc mmv$avail_modified_queue_max
*copyc mmv$dynamic_aging_enabled
*copyc mmv$dynamic_avail_emergency_min
*copyc mmv$dynamic_available_floor
*copyc mmv$dynamic_available_max
*copyc mmv$dynamic_available_min
*copyc mmv$dynamic_neg_increment_max
*copyc mmv$dynamic_pos_increment_max
*copyc mmv$gpql
*copyc mmv$io_error_q_age_interval
*copyc mmv$jws_queue_age_interval
*copyc mmv$last_active_shared_queue
*copyc mmv$max_pages_no_file
*copyc mmv$manage_memory_utility
*copyc mmv$mem_wait_q_dequeue_interval
*copyc mmv$min_avail_pages
*copyc mmv$page_streaming_prestream
*copyc mmv$page_streaming_random_limit
*copyc mmv$page_streaming_reads
*copyc mmv$page_streaming_threshold
*copyc mmv$page_streaming_transfer
*copyc mmv$periodic_call_interval
*copyc mmv$shared_queue_age_interval
*copyc mmv$swapping_aic
*copyc mmv$tick_time
*copyc mmv$total_page_frames
*copyc mmv$write_aged_out_pages
?? OLDTITLE ??
?? NEWTITLE := 'Glocal Declarations Delcared by This Module', EJECT ??

  VAR
    v$dissqa_data: [STATIC, READ] array
          [mmc$pq_shared_first .. mmc$pq_shared_first_site] of string (20) := ['TASK_SERVICE        ',
          'EXECUTABLE_FILE     ', 'NON_EXECUTABLE_FILE ', 'DEVICE_FILE         ', 'FILE_SERVER         ',
          'OTHER               ', 'SITE_XX             '];

?? OLDTITLE ??
?? NEWTITLE := 'P$RESET_DYNAMIC_AGING', EJECT ??

{  When this procedure needs to be changed, do not forget to also update
{  p$reset_dynamic_aging in MMM$MONITOR_REQUEST_PROCESSOR.

  PROCEDURE p$reset_dynamic_aging
    (    queue: mmt$page_frame_queue_id;
         age_interval_modified: mmt$mmu_reset_value;
         age_interval_unmodified: mmt$mmu_reset_value;
         minimum: mmt$mmu_reset_value;
         maximum: mmt$mmu_reset_value);

?? NEWTITLE := '[inline] F$VALUE', EJECT ??

    FUNCTION [INLINE] f$value
      (    specified_value: mmt$mmu_reset_value;
           current_value: integer;
           nominal_value: integer;
           default_value: integer): integer;

      CASE specified_value.kind OF
      = mmc$mmu_nominal_value =
        f$value := nominal_value;

      = mmc$mmu_default_value =
        f$value := default_value;

      = mmc$mmu_current_value =
        f$value := current_value;

      = mmc$mmu_specified_value =
        f$value := specified_value.specified_value;
      CASEND;

    FUNCEND f$value;
?? OLDTITLE ??
?? EJECT ??
    mmv$gpql [queue].queue_cyclic_age := 0;

    mmv$gpql [queue].age_interval_actual_modified := f$value
          (age_interval_modified, mmv$gpql [queue].age_interval_actual_modified,
          mmv$gpql [queue].age_interval_nominal_modified, mmv$manage_memory_utility.gpql [queue].
          age_interval_actual_modified);
    mmv$gpql [queue].age_interval_actual_unmodified := f$value
          (age_interval_unmodified, mmv$gpql [queue].age_interval_actual_unmodified,
          mmv$gpql [queue].age_interval_nominal_unmodified, mmv$manage_memory_utility.gpql [queue].
          age_interval_actual_unmodified);

    mmv$gpql [queue].minimum_actual := f$value (minimum, mmv$gpql [queue].minimum_actual,
          mmv$gpql [queue].minimum_nominal, mmv$manage_memory_utility.gpql [queue].minimum_actual);

    mmv$gpql [queue].maximum_actual := f$value (maximum, mmv$gpql [queue].maximum_actual,
          mmv$gpql [queue].maximum_nominal, mmv$manage_memory_utility.gpql [queue].maximum_actual);

    mmv$gpql [queue].maximum_actual_cycle := f$value (maximum, mmv$gpql [queue].maximum_actual_cycle,
          mmv$gpql [queue].maximum_nominal, mmv$manage_memory_utility.gpql [queue].maximum_actual);

  PROCEND p$reset_dynamic_aging;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$disable_transient_segments', EJECT ??

{ PURPOSE:
{   Thiss procedure is used at deadstart time to temporarily disable transient segments. This is required
{   until Device Manager SPACE MANAGER is running. Otherwise, Space manager may get transient segments in
{   its address space. If the signal to allocate the backing file occurs when MAT space is low, space
{   manager may hang.

  PROCEDURE [XDCL] mmp$disable_transient_segments;

    mmv$max_pages_no_file := -mmv$max_pages_no_file - 1;

  PROCEND mmp$disable_transient_segments;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$enable_transient_segments', EJECT ??

  PROCEDURE [XDCL, #GATE] mmp$enable_transient_segments;

    IF mmv$max_pages_no_file < 0 THEN
      mmv$max_pages_no_file := -mmv$max_pages_no_file - 1;
    IFEND;

  PROCEND mmp$enable_transient_segments;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$fetch_dynamic_aging_enab_r1', EJECT ??

{ PURPOSE:
{   This procedure retrieves the dynamic aging enabled attribute.

  PROCEDURE [XDCL, #GATE] mmp$fetch_dynamic_aging_enab_r1
    (VAR dynamic_aging_enabled: boolean);

    dynamic_aging_enabled := mmv$dynamic_aging_enabled;

  PROCEND mmp$fetch_dynamic_aging_enab_r1;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$fetch_manage_memory_data_r1', EJECT ??

{ PURPOSE:
{   This procedure retrieves the data that can be changed by the Manage Memory Utility.  Although only part
{   of the data is usually needed, the interface between ring1 and the Manage_Memory Utility is kept simple
{   by passing all of the possible data required.

  PROCEDURE [XDCL, #GATE] mmp$fetch_manage_memory_data_r1
    (VAR queues: mmt$global_page_queue_list;
     VAR ma_values: mmt$mmu_ma_values;
     VAR gpql_default: mmt$mmu_gpql_default;
     VAR ma_default: mmt$mmu_ma_default);

    VAR
      ma_index: mmt$mmu_memory_attributes,
      queue_id: mmt$page_frame_queue_id,
      source_q_p: ^mmt$global_page_queue_list_ent,
      target_q_p: ^mmt$global_page_queue_list_ent;

    FOR ma_index := LOWERBOUND (mmv$manage_memory_utility.ma) TO UPPERBOUND (mmv$manage_memory_utility.ma) DO
      ma_default [ma_index] := mmv$manage_memory_utility.ma [ma_index].default;
      IF mmv$manage_memory_utility.ma [ma_index].value_type = mmc$mmu_mvt_integer THEN
        ma_values [ma_index] := mmv$manage_memory_utility.ma [ma_index].integer_p^;
      ELSE { mmc$mmu_mvt_byte }
        ma_values [ma_index] := mmv$manage_memory_utility.ma [ma_index].byte_p^;
      IFEND;
    FOREND;

    FOR queue_id := mmc$pq_shared_first TO mmc$pq_shared_last DO
      source_q_p := ^mmv$gpql [queue_id];
      target_q_p := ^queues [queue_id];

{We also return the current count for display purposes. But it's just a one way path!
      target_q_p^.pqle.count := source_q_p^.pqle.count;

      target_q_p^.queue_cyclic_age := source_q_p^.queue_cyclic_age;
      target_q_p^.queue_age_interval := source_q_p^.queue_age_interval;
      target_q_p^.encrease_min_enable_dynamic_age := source_q_p^.encrease_min_enable_dynamic_age;

      target_q_p^.age_interval_actual_modified := source_q_p^.age_interval_actual_modified;
      target_q_p^.age_interval_actual_unmodified := source_q_p^.age_interval_actual_unmodified;
      target_q_p^.age_interval_nominal_modified := source_q_p^.age_interval_nominal_modified;
      target_q_p^.age_interval_nominal_unmodified := source_q_p^.age_interval_nominal_unmodified;
      target_q_p^.age_interval_modified_max := source_q_p^.age_interval_modified_max;
      target_q_p^.age_interval_modified_min := source_q_p^.age_interval_modified_min;
      target_q_p^.age_interval_unmodified_max := source_q_p^.age_interval_unmodified_max;
      target_q_p^.age_interval_unmodified_min := source_q_p^.age_interval_unmodified_min;
      target_q_p^.age_interval_neg_inc_modified := source_q_p^.age_interval_neg_inc_modified;
      target_q_p^.age_interval_neg_inc_unmodified := source_q_p^.age_interval_neg_inc_unmodified;
      target_q_p^.age_interval_pos_inc_modified := source_q_p^.age_interval_pos_inc_modified;
      target_q_p^.age_interval_pos_inc_unmodified := source_q_p^.age_interval_pos_inc_unmodified;

      target_q_p^.minimum_actual := source_q_p^.minimum_actual;
      target_q_p^.minimum_nominal := source_q_p^.minimum_nominal;
      target_q_p^.minimum_min := source_q_p^.minimum_min;
      target_q_p^.minimum_max := source_q_p^.minimum_max;
      target_q_p^.minimum_neg_inc := source_q_p^.minimum_neg_inc;
      target_q_p^.minimum_neg_inc_pc := source_q_p^.minimum_neg_inc_pc;
      target_q_p^.minimum_pos_inc := source_q_p^.minimum_pos_inc;
      target_q_p^.minimum_pos_inc_pc := source_q_p^.minimum_pos_inc_pc;

      target_q_p^.maximum_actual_cycle := source_q_p^.maximum_actual_cycle;
      target_q_p^.maximum_actual := source_q_p^.maximum_actual;
      target_q_p^.maximum_nominal := source_q_p^.maximum_nominal;
      target_q_p^.maximum_min := source_q_p^.maximum_min;
      target_q_p^.maximum_max := source_q_p^.maximum_max;
      target_q_p^.maximum_neg_inc := source_q_p^.maximum_neg_inc;
      target_q_p^.maximum_neg_inc_pc := source_q_p^.maximum_neg_inc_pc;
      target_q_p^.maximum_pos_inc := source_q_p^.maximum_pos_inc;
      target_q_p^.maximum_pos_inc_pc := source_q_p^.maximum_pos_inc_pc;

      target_q_p^.age_cycles := source_q_p^.age_cycles;
    FOREND;

    gpql_default := mmv$manage_memory_utility.gpql;

  PROCEND mmp$fetch_manage_memory_data_r1;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$fetch_site_active_q_cnt_r1', EJECT ??

{ PURPOSE:
{   This procedure retrieves the site active queue count.

  PROCEDURE [XDCL, #GATE] mmp$fetch_site_active_q_cnt_r1
    (VAR site_active_queue_count: 0 .. mmc$pq_shared_num_sites);

    site_active_queue_count := mmv$last_active_shared_queue - mmc$pq_shared_last_sys;

  PROCEND mmp$fetch_site_active_q_cnt_r1;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$get_page_q_counts', EJECT ??

  PROCEDURE [XDCL, #GATE] mmp$get_page_q_counts
    (VAR counts: mmt$page_q_counts);

    VAR
      i: integer,
      ijle_p: ^jmt$initiated_job_list_entry,
      index: integer,
      j: integer;

    FOR index := LOWERVALUE (mmt$global_page_queue_index) TO UPPERVALUE (mmt$global_page_queue_index) DO
      counts.q_counts [index] := mmv$gpql [index].pqle.count;
    FOREND;
    counts.site_defined_queues_active := mmv$last_active_shared_queue - mmc$pq_shared_last_sys;

    { Now add up pages associated with each job.

    counts.long_wait_count := 0;
    counts.swap_resident_count := 0;
    counts.q_counts [mmc$pq_job_fixed] := 0;
    counts.q_counts [mmc$pq_job_io_error] := 0;
    counts.q_counts [mmc$pq_job_working_set] := 0;

  /scan_ijl/
    FOR i := LOWERBOUND (jmv$ijl_p.block_p^) TO jmv$ijl_p.max_block_in_use DO
      IF jmv$ijl_p.block_p^ [i].index_p <> NIL THEN

      /inner_loop/
        FOR j := LOWERVALUE (jmt$ijl_block_index) TO UPPERVALUE (jmt$ijl_block_index) DO
          ijle_p := ^jmv$ijl_p.block_p^ [i].index_p^ [j];

          IF ijle_p^.swap_status = jmc$iss_executing THEN
            counts.q_counts [mmc$pq_job_fixed] := counts.q_counts [mmc$pq_job_fixed] +
                  ijle_p^.job_page_queue_list [mmc$pq_job_fixed].count;
            counts.q_counts [mmc$pq_job_io_error] := counts.q_counts [mmc$pq_job_io_error] +
                  ijle_p^.job_page_queue_list [mmc$pq_job_io_error].count;
            counts.q_counts [mmc$pq_job_working_set] := counts.q_counts [mmc$pq_job_working_set] +
                  ijle_p^.job_page_queue_list [mmc$pq_job_working_set].count;

          ELSEIF (ijle_p^.swap_status >= jmc$iss_idle_tasks_initiated) AND
                (ijle_p^.swap_status <= jmc$iss_swapped_io_cannot_init) THEN
            counts.long_wait_count := counts.long_wait_count +
                  ijle_p^.job_page_queue_list [mmc$pq_job_fixed].
                  count + ijle_p^.job_page_queue_list [mmc$pq_job_io_error].count +
                  ijle_p^.job_page_queue_list [mmc$pq_job_working_set].count;

          ELSEIF (ijle_p^.swap_status >= jmc$iss_initiate_swapout_io) AND
                (ijle_p^.swap_status <= jmc$iss_swapped_io_complete) THEN
            counts.swap_resident_count := counts.swap_resident_count + ijle_p^.
                  job_page_queue_list [mmc$pq_job_fixed].count + ijle_p^.
                  job_page_queue_list [mmc$pq_job_io_error].count + ijle_p^.
                  job_page_queue_list [mmc$pq_job_working_set].count;
          IFEND;
        FOREND /inner_loop/;
      IFEND;
    FOREND /scan_ijl/;

  PROCEND mmp$get_page_q_counts;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$reset_dynamic_aging_r1', EJECT ??

  PROCEDURE [XDCL, #GATE] mmp$reset_dynamic_aging_r1
    (    queues: set of mmt$global_page_queue_index;
         reset_values: mmt$mmu_reset_values);

    VAR
      queue_id: mmt$page_frame_queue_id;

    FOR queue_id := mmc$pq_shared_first TO mmc$pq_shared_last DO
      IF queue_id IN queues THEN
        p$reset_dynamic_aging (queue_id, reset_values [mmc$mmu_age_interval_modified],
              reset_values [mmc$mmu_age_interval_unmodified], reset_values [mmc$mmu_minimum],
              reset_values [mmc$mmu_maximum]);
      IFEND;
    FOREND;

  PROCEND mmp$reset_dynamic_aging_r1;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$store_manage_memory_data_r1', EJECT ??

{ PURPOSE:
{   This procedure stores the data that can be changed by the Manage Memory Utility.  Although only part of
{   the data is usually needed, the interface between ring1 and the Manage_Memory Utility is kept simple by
{   passing all of the possible data required.

  PROCEDURE [XDCL, #GATE] mmp$store_manage_memory_data_r1
    (    reset_dynamic_aging: boolean;
         queues: mmt$global_page_queue_list;
         ma_values: mmt$mmu_ma_values;
     VAR status: ost$status);

    VAR
      count: integer,
      ma_index: mmt$mmu_memory_attributes,
      max_available_pages: integer,
      queue_id: mmt$page_frame_queue_id,
      reset_value: mmt$mmu_reset_value,
      source_q_p: ^mmt$global_page_queue_list_ent,
      target_q_p: ^mmt$global_page_queue_list_ent;

?? NEWTITLE := 'p$append_queue_name', EJECT ??

    PROCEDURE p$append_queue_name
      (    queue_id: mmt$page_frame_queue_id;
       VAR status: ost$status);

      TYPE
        t$queue_part = record
          case 0 .. 2 of
          = 0 =
            data: string (21),
          = 1 =
            filler_1: string (1),
            queue: string (20),
          = 2 =
            filler_2: string (1),
            site_name: string (5),
            site_number: string (2),
          casend,
        recend;

      VAR
        ignore_status: ost$status,
        name: t$queue_part;

      name.data := '';
      IF queue_id < mmc$pq_shared_first_site THEN
        name.queue := v$dissqa_data [queue_id];
      ELSE
        name.queue := v$dissqa_data [mmc$pq_shared_first_site];
        clp$convert_integer_to_rjstring ((queue_id - mmc$pq_shared_last_sys), 10, FALSE, '0',
              name.site_number, ignore_status);
      IFEND;

      osp$append_status_parameter (osc$status_parameter_delimiter, name.data, status);

    PROCEND p$append_queue_name;
?? OLDTITLE ??
?? EJECT ??
    status.normal := TRUE;

{Verify Attributes
{  - MAX_AVAILABLE_PAGES is still too optimistic!
    max_available_pages := mmv$total_page_frames - ma_values [mmc$mmu_ma_minap] - ma_values [mmc$mmu_ma_aal2];

{For now, we verify the total of the Shared Q's against MAX_AVAILABLE_PAGES.
{More validation might be necessary, but setting this attribute too high can shurly hang the system!
    count := 0;
    FOR queue_id := mmc$pq_shared_first TO mmc$pq_shared_last DO
      IF queues [queue_id].minimum_nominal > max_available_pages THEN
        osp$set_status_abnormal ('MM', mme$min_shared_q_size_exceeded, 'Minimum', status);
        p$append_queue_name (queue_id, status);
        osp$append_status_integer (osc$status_parameter_delimiter, queues [queue_id].minimum_nominal, 10,
              FALSE, status);
        osp$append_status_integer (osc$status_parameter_delimiter, max_available_pages, 10, FALSE, status);
        RETURN;
      IFEND;
      count := count + queues [queue_id].minimum_nominal;
    FOREND;

    IF count > max_available_pages THEN
      osp$set_status_abnormal ('MM', mme$min_shared_q_size_exceeded, 'Minimum', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'Total of all Shared Queues', status);
      osp$append_status_integer (osc$status_parameter_delimiter, count, 10, FALSE, status);
      osp$append_status_integer (osc$status_parameter_delimiter, max_available_pages, 10, FALSE, status);
      RETURN;
    IFEND;

    reset_value.kind := mmc$mmu_nominal_value;

    { Store the values contained in the input into the memory attributes and into the queue header.  Be sure
    { that the link headers in the queue headers are not changed.

    FOR ma_index := LOWERBOUND (mmv$manage_memory_utility.ma) TO UPPERBOUND (mmv$manage_memory_utility.ma) DO
      IF mmv$manage_memory_utility.ma [ma_index].value_type = mmc$mmu_mvt_integer THEN
        mmv$manage_memory_utility.ma [ma_index].integer_p^ := ma_values [ma_index];
      ELSE { mmc$mmu_mvt_byte }
        mmv$manage_memory_utility.ma [ma_index].byte_p^ := ma_values [ma_index];
      IFEND;
    FOREND;

    FOR queue_id := mmc$pq_shared_first TO mmc$pq_shared_last DO
      source_q_p := ^queues [queue_id];
      target_q_p := ^mmv$gpql [queue_id];

      target_q_p^.queue_age_interval := source_q_p^.queue_age_interval;
      target_q_p^.encrease_min_enable_dynamic_age := source_q_p^.encrease_min_enable_dynamic_age;

      target_q_p^.age_interval_nominal_modified := source_q_p^.age_interval_nominal_modified;
      target_q_p^.age_interval_nominal_unmodified := source_q_p^.age_interval_nominal_unmodified;
      target_q_p^.age_interval_modified_max := source_q_p^.age_interval_modified_max;
      target_q_p^.age_interval_modified_min := source_q_p^.age_interval_modified_min;
      target_q_p^.age_interval_unmodified_max := source_q_p^.age_interval_unmodified_max;
      target_q_p^.age_interval_unmodified_min := source_q_p^.age_interval_unmodified_min;
      target_q_p^.age_interval_neg_inc_modified := source_q_p^.age_interval_neg_inc_modified;
      target_q_p^.age_interval_neg_inc_unmodified := source_q_p^.age_interval_neg_inc_unmodified;
      target_q_p^.age_interval_pos_inc_modified := source_q_p^.age_interval_pos_inc_modified;
      target_q_p^.age_interval_pos_inc_unmodified := source_q_p^.age_interval_pos_inc_unmodified;

      target_q_p^.minimum_nominal := source_q_p^.minimum_nominal;
      target_q_p^.minimum_min := source_q_p^.minimum_min;
      target_q_p^.minimum_max := source_q_p^.minimum_max;
      target_q_p^.minimum_neg_inc := source_q_p^.minimum_neg_inc;
      target_q_p^.minimum_neg_inc_pc := source_q_p^.minimum_neg_inc_pc;
      target_q_p^.minimum_pos_inc := source_q_p^.minimum_pos_inc;
      target_q_p^.minimum_pos_inc_pc := source_q_p^.minimum_pos_inc_pc;

      target_q_p^.maximum_nominal := source_q_p^.maximum_nominal;
      target_q_p^.maximum_min := source_q_p^.maximum_min;
      target_q_p^.maximum_max := source_q_p^.maximum_max;
      target_q_p^.maximum_neg_inc := source_q_p^.maximum_neg_inc;
      target_q_p^.maximum_neg_inc_pc := source_q_p^.maximum_neg_inc_pc;
      target_q_p^.maximum_pos_inc := source_q_p^.maximum_pos_inc;
      target_q_p^.maximum_pos_inc_pc := source_q_p^.maximum_pos_inc_pc;

      target_q_p^.age_cycles := source_q_p^.age_cycles;

      IF reset_dynamic_aging THEN
        p$reset_dynamic_aging (queue_id, reset_value, reset_value, reset_value, reset_value);
      IFEND;
    FOREND;

  PROCEND mmp$store_manage_memory_data_r1;
?? OLDTITLE ??
?? NEWTITLE := 'mmp$store_site_active_q_cnt_r1', EJECT ??

{ PURPOSE:
{   This procedure changes the site active queue count value.

  PROCEDURE [XDCL, #GATE] mmp$store_site_active_q_cnt_r1
    (    new_site_active_queue_count: 0 .. mmc$pq_shared_num_sites;
     VAR status: ost$status);

    VAR
      index: mmt$page_frame_queue_id,
      pages: integer;

    status.normal := TRUE;

    IF (mmc$pq_shared_last_sys + new_site_active_queue_count) < mmv$last_active_shared_queue THEN
      pages := 0;
      FOR index := (mmc$pq_shared_last_sys + new_site_active_queue_count + 1)
            TO mmv$last_active_shared_queue DO
        pages := pages + mmv$gpql [index].pqle.count;
      FOREND;
      IF pages <> 0 THEN
        osp$set_status_abnormal ('MM', mme$site_shared_queues_active, '', status);
        RETURN; {----->
      IFEND;
    IFEND;

    mmv$last_active_shared_queue := mmc$pq_shared_last_sys + new_site_active_queue_count;

  PROCEND mmp$store_site_active_q_cnt_r1;
?? OLDTITLE ??
MODEND mmm$ring1_helper;
