?? RIGHT := 110 ??
*copyc osd$default_pragmats
?? NEWTITLE := 'NOS/VE : device management' ??
?? NEWTITLE := '  module header', EJECT ??
MODULE dmm$run_asynchronous_tasks;

{  PURPOSE:
{    This module exists to provide entry points for asynchronous DM
{    tasks.
{  DESIGN:
{    Entry points are declared.  The tasks which they define spend
{    most of their time asleep in this module.  When there is work to do
{    a call is made down to ring 1.
?? PUSH (LISTEXT := ON) ??
*copyc ost$global_task_id
*copyc ost$heap
*copyc ost$status
*copyc dmt$active_volume_table_index
  ?? POP ??
?? OLDTITLE ??
?? NEWTITLE := '  XREF Procedures', EJECT ??
*copyc dmp$get_out_of_space_sets
*copyc pmp$get_executing_task_gtid
*copyc pmp$find_executing_task_xcb
*copyc mmp$assign_mass_storage
*copyc mmp$enable_transient_segments
*copyc pmp$wait
*copyc dmp$dev_mgmt_table_update
*copyc dmp$management_of_volume_space
*copyc tmp$save_system_task_id
*copyc dmp$set_lower_priority
*copyc syp$cleanup_heap_pages
*copyc dmp$split_allocation_log
*copyc ofp$execute_display_task
?? OLDTITLE ??
?? NEWTITLE := '  XREF Variables', EJECT ??
*copyc gfv$null_sfid
*copyc jmv$executing_within_system_job
*copyc dmv$internal_task_delay_values
*copyc dmv$active_volume_table
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] dmp$administer_allocation_log', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$administer_allocation_log ALIAS 'dmxaalg';

*copyc dmh$administer_allocation_log

    VAR
      taskid: ost$global_task_id,
      time_delay: 0 .. 0ffffffffffff(16),
      status: ost$status;

    IF NOT jmv$executing_within_system_job THEN
      RETURN;
    IFEND;

    pmp$get_executing_task_gtid (taskid);

    dmp$set_lower_priority (split_al_task, taskid);

    tmp$save_system_task_id (tmc$stid_dm_split_al, TRUE, status);

    WHILE TRUE DO
      time_delay := dmv$split_allocation_log_delay;
      pmp$wait (time_delay, time_delay);
      dmp$split_allocation_log (FALSE, status);
    WHILEND;

  PROCEND dmp$administer_allocation_log;

?? OLDTITLE ??
?? NEWTITLE := '  [XDCL, #GATE] dmp$administer_device_log', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$administer_device_log ALIAS 'dmxadlg';

*copyc dmh$administer_device_log

    VAR
      taskid: ost$global_task_id,
      time_delay: 0 .. 0ffffffffffff(16),
      status: ost$status,
      xcb_p: ^ost$execution_control_block;

    IF NOT jmv$executing_within_system_job THEN
      RETURN;
    IFEND;

{ The following calls to assign space to the stack segments are
{ required to prevent page faulting for the stacks. Please do not
{ modify or delete these calls.

    pmp$find_executing_task_xcb (xcb_p);

    mmp$assign_mass_storage (xcb_p^.xp.tos_registers [3].pva.seg, gfv$null_sfid, 4096, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    mmp$assign_mass_storage (xcb_p^.xp.tos_registers [2].pva.seg, gfv$null_sfid, 4096, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    mmp$assign_mass_storage (xcb_p^.xp.tos_registers [1].pva.seg, gfv$null_sfid, 4096, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pmp$get_executing_task_gtid (taskid);

    dmp$set_lower_priority (administer_log_task, taskid);

    tmp$save_system_task_id (tmc$stid_administer_log, TRUE, status);

    WHILE TRUE DO
      time_delay := dmv$process_device_log_delay;
      pmp$wait (time_delay, time_delay);
      dmp$dev_mgmt_table_update;

      syp$cleanup_heap_pages;
    WHILEND;

  PROCEND dmp$administer_device_log;

?? OLDTITLE ??
  ?? NEWTITLE := '[XDCL, #GATE] dmp$volume_space_management', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$volume_space_management;

    VAR
      new_classes: dmt$class,
      new_classes_out: boolean,
      new_count: integer,
      new_index: integer,
      old_count: integer,
      old_index: integer,
      p_old: ^dmt$out_of_space_sets,
      p_new: ^dmt$out_of_space_sets,
      p_save: ^dmt$out_of_space_sets,
      set_name: stt$set_name,
      taskid: ost$global_task_id,
      time_delay: 0 .. 0ffffffffffff(16),
      previous_added: integer,
      dmv$q_devices_added: [XREF] integer,
      status: ost$status,
      xcb_p: ^ost$execution_control_block;

    IF NOT jmv$executing_within_system_job THEN
      RETURN;
    IFEND;

    mmp$enable_transient_segments;

{ The following calls to assign space to the stack segments are
{ required to prevent page faulting for the stacks. Please do not
{ modify or delete these calls.

    pmp$find_executing_task_xcb (xcb_p);

    mmp$assign_mass_storage (xcb_p^.xp.tos_registers [3].pva.seg, gfv$null_sfid, 4096, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    mmp$assign_mass_storage (xcb_p^.xp.tos_registers [2].pva.seg, gfv$null_sfid, 4096, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    mmp$assign_mass_storage (xcb_p^.xp.tos_registers [1].pva.seg, gfv$null_sfid, 4096, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    mmp$assign_mass_storage (osc$segnum_task_private_heap, gfv$null_sfid, 50000, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pmp$get_executing_task_gtid (taskid);

    dmp$set_lower_priority (volume_space_management_task, taskid);

    tmp$save_system_task_id (tmc$stid_volume_space_managemnt, TRUE, status);

    PUSH p_old: [1 .. UPPERBOUND (dmv$active_volume_table.table_p^) + 1];
    PUSH p_new: [1 .. UPPERBOUND (dmv$active_volume_table.table_p^) + 1];
    old_count := 0;
    previous_added := 0;

    WHILE TRUE DO
      dmp$management_of_volume_space;

      dmp$get_out_of_space_sets (p_new^, new_count);

      new_classes_out := FALSE;
      FOR new_index := 1 TO new_count DO
        new_classes := p_new^ [new_index].classes;
        IF (new_classes <> $dmt$class []) THEN
          set_name := p_new^ [new_index].set_name;
          old_index := new_index;
          IF (old_index > old_count) OR (set_name <> p_old^ [old_index].set_name) THEN
            old_index := 1;
            WHILE (old_index <= old_count) AND (set_name <> p_old^ [old_index].set_name) DO
              old_index := old_index + 1;
            WHILEND;
          IFEND;
          IF (old_index > old_count) OR ((new_classes - p_old^ [old_index].classes) <> $dmt$class []) THEN
            new_classes_out := TRUE;
          IFEND;
        IFEND;
      FOREND;

      p_save := p_old;
      p_old := p_new;
      p_new := p_save;
      old_count := new_count;

      IF new_classes_out OR (dmv$q_devices_added <> previous_added) THEN
        previous_added := dmv$q_devices_added;
        ofp$execute_display_task ('$LOCAL.DISPLAY_B', 'MASS_STORAGE                   ', status);
      IFEND;

      time_delay := dmv$volume_table_space_delay;
      pmp$wait (time_delay, time_delay);
    WHILEND;

  PROCEND dmp$volume_space_management;

MODEND dmm$run_asynchronous_tasks;
