?? NEWTITLE := 'NOS/VE Device Management' ??
MODULE dmm$mainframe_file_list_manager;
?? RIGHT := 110 ??

{ PURPOSE:
{
{   The purpose of this module is to manage access to the mainframe file list
{ (MFL).  This includes creating the MFL, deleting it and assigning entires
{ from it.
{
{ DESIGN:
{
{   The MFL consists of an array of word aligned integers.  Each entry contains
{ a Device File List (DFL) index that is available to be assigned, or zero if
{ the MFL entry is empty.  Compare swap locking is used to take available DFL
{ indicies from the table and replace them with the zero flag.  When the table
{ is empty, it is filled by the space management task.

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cyd$cybil_structure_definitions
*copyc dmt$active_volume_table_index
*copyc dmt$device_file_list_index
*copyc dmt$error_condition_codes
*copyc dmt$mainframe_device_file_list
*copyc ost$status
?? POP ??
*copyc dmp$get_mfl_pointer
*copyc dmp$lock_avt_entry
*copyc dmp$unlock_avt_entry
*copyc osp$fetch_locked_variable
*copyc osp$set_locked_variable
*copyc osp$system_error
*copyc pmp$delay
*copyc tmp$ready_system_task1
*copyc i#fill
*copyc dmv$active_volume_table
*copyc osv$mainframe_pageable_heap
*copyc osv$mainframe_wired_heap
?? TITLE := '  Global Definitions', EJECT ??

  TYPE
    t$converter_type = record
      case boolean of
      = FALSE =
        p_adaptable: cyt$adaptable_array_pointer,
      = TRUE =
        p_mfl: ^dmt$ms_mf_device_file_list,
      casend,
    recend;

?? TITLE := '  dmp$create_mfl', EJECT ??

  PROCEDURE [XDCL] dmp$create_mfl
    (VAR p_mfl: cyt$adaptable_array_pointer);

    VAR
      converter: t$converter_type;

    ALLOCATE converter.p_mfl: [1 .. dmc$cm_dflt_entries] IN osv$mainframe_pageable_heap^;
    i#fill ($CHAR (0), ^converter.p_mfl^, #SIZE (converter.p_mfl^));

    p_mfl := converter.p_adaptable;

  PROCEND dmp$create_mfl;
?? TITLE := '  dmp$delete_mfl', EJECT ??

  PROCEDURE [XDCL] dmp$delete_mfl
    (VAR p_mfl {input, output} : cyt$adaptable_array_pointer);

    VAR
      converter: t$converter_type;

    converter.p_adaptable := p_mfl;
    IF (converter.p_mfl <> NIL) THEN
      FREE converter.p_mfl IN osv$mainframe_pageable_heap^;
      p_mfl := converter.p_adaptable;
    IFEND;

  PROCEND dmp$delete_mfl;
?? TITLE := '  dmp$get_unused_mfl_entry', EJECT ??

  PROCEDURE [XDCL] dmp$get_unused_mfl_entry
    (    avt_index: dmt$active_volume_table_index;
     VAR dfl_ordinal: dmt$device_file_list_index;
     VAR status: ost$status);

    VAR
      mf_file_list_index: dmt$ms_mf_device_file_list_ord,
      current_value: integer,
      actual: integer,
      successful: boolean,
      dflt_table_status: dmt$ms_volume_table_status,
      p_mfl: ^dmt$ms_mf_device_file_list;

    status.normal := TRUE;

    dmp$get_mfl_pointer (avt_index, p_mfl);
    IF p_mfl = NIL THEN
      osp$system_error ('NIL pointer to mfl - dmp$get_unused_mfl_entry', NIL);
    IFEND;

    WHILE TRUE DO
      FOR mf_file_list_index := 1 TO UPPERBOUND (p_mfl^) DO
        osp$fetch_locked_variable (p_mfl^ [mf_file_list_index].ordinal, current_value);
        IF current_value <> 0 THEN
          osp$set_locked_variable (p_mfl^ [mf_file_list_index].ordinal, current_value, 0, actual, successful);
          IF successful THEN
            dfl_ordinal := current_value;
            RETURN; {----->
          IFEND;
        IFEND;
      FOREND;

      dflt_table_status := $dmt$ms_volume_table_status [dmc$dflt_update_required];

      dmp$lock_avt_entry (avt_index);
      dmv$active_volume_table.table_p^ [avt_index].mass_storage.disk_table_status :=
            dmv$active_volume_table.table_p^ [avt_index].mass_storage.disk_table_status + dflt_table_status;
      dmp$unlock_avt_entry (avt_index);

      tmp$ready_system_task (tmc$stid_volume_space_managemnt, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;

      pmp$delay (4000, status);
    WHILEND;

  PROCEND dmp$get_unused_mfl_entry;

MODEND dmm$mainframe_file_list_manager;
