



		    illegal_procedure.pl1           11/11/89  1139.4r w 11/11/89  0839.1       17298



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1982 *
        *                                                         *
        *********************************************************** */
%;
/* ******************************************************
   *                                                    *
   *                                                    *
   * Copyright (c) 1972 by Massachusetts Institute of   *
   * Technology and Honeywell Information Systems, Inc. *
   *                                                    *
   *                                                    *
   ****************************************************** */

/*
   Last Modified (Date and Reason):
   10/15/73 Steve Webber -- Initial coding.
   10/09/74 Lee Scheffler - Add auditing of bona fide illegal procedure faults.
   06/07/76 Bernard Greenberg- mc.resignal for truncation fault, incl. internal procedure for lth.
   85-01-15 EJ Sharpe - deleted all but set_pl1_machine entry since unused
   */

illegal_procedure$set_pl1_machine_mode: proc (new_mode, old_mode);

/* This entry will change the state of a process from a "pl1 machine" to a "bare machine".
   In the pl1 machine mode certain illegal procedure are ignored. In the bare
   machine mode these faults are signalled to the user. */

dcl (new_mode, old_mode) fixed bin;
dcl  pds$pl1_machine fixed bin ext;
dcl  i fixed bin;


	i = pds$pl1_machine;			/* return old value of the mode */
	pds$pl1_machine = new_mode;			/* change the mode for the process */
	old_mode = i;				/* return the copied old value */
	return;

     end illegal_procedure$set_pl1_machine_mode;
  



		    mos_memory_check.pl1            11/11/89  1139.4rew 11/11/89  0839.1       67878



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1982 *
        *                                                         *
        * Copyright (c) 1972 by Massachusetts Institute of        *
        * Technology and Honeywell Information Systems, Inc.      *
        *                                                         *
        *********************************************************** */

/* format: style4 */

/* MOS_MEMORY_CHECK: This procedure scans memorys to check for MOS memory EDAC errors to be logged. */

/* Written April 1976 by Larry Johnson */
/* The initial version will check only the low order memory on each controller */
/* Modified June 1976 by Larry Johnson to check all memories on a controller */
/* Modified September 1977 by Larry Johnson for new memory board types */
/* Modified October 1981 by M.R. Jordan for new 64K chip memory */
/* Modified February 1985 by EJ Sharpe to not log binary value for polling interval, add format */

mos_memory_check: proc (arg_mem, arg_store, arg_data, arg_code);

dcl  arg_mem (0:31) char (1) unal;
dcl  arg_store (0:31) char (2) unal;
dcl  arg_data (0:31) fixed bin (71);			/* Array of maintenance registers */
dcl  arg_code fixed bin (35);
dcl  arg_time fixed bin;

dcl  port fixed bin;
dcl  rscr_result fixed bin (71);
dcl  poll_entry bit (1) init ("0"b);			/* Set if called by polling */
dcl  time fixed bin;
dcl  (store_a_index, store_b_index) fixed bin (5);	/* Scas indexes for pmut$rscr */
dcl  mem char (1);
dcl  aloud fixed bin;

dcl  spoke (0:31) bit (1) int static init ((32) (1)"0"b);

dcl  never fixed bin (52) int static options (constant)
	init (1111111111111111111111111111111111111111111111111111b);


dcl  letter (0:7) char (1) unal int static options (constant) init ("a", "b", "c", "d", "e", "f", "g", "h");

dcl  privileged_mode_ut$rscr entry (fixed bin (5), fixed bin (6), fixed bin (71));
dcl  clock_ entry returns (fixed bin (71));
dcl  syserr entry options (variable);
dcl  syserr$binary entry options (variable);

dcl  tc_data$mos_polling_time ext fixed bin (52);
dcl  tc_data$mos_polling_interval ext fixed bin;
dcl  pds$process_group_id ext char (32) aligned;
dcl  pds$processid ext bit (36) aligned;
dcl  error_table_$lock_wait_time_exceeded ext fixed bin (35);

dcl  cleanup condition;

dcl  (addr, stac, stacq) builtin;
%page;
/* First, lock the reconfig lock */

	arg_code = 0;

start:

	on cleanup call clean_up;

	if ^stac (addr (scs$reconfig_lock), pds$processid) then do;
	     if poll_entry then tc_data$mos_polling_time = clock_ () + 60000000; /* Try again in 1 minute */
	     else arg_code = error_table_$lock_wait_time_exceeded;
	     return;
	end;
	scs$reconfig_locker_id = pds$process_group_id;

/* Now scan looking for memorys */

	scrp = addr (rscr_result);

	do port = 0 to 7;				/* Scan all controlers */

	     if scs$controller_data.online (port) then do;/* Found active memory */
		if ^scs$controller_data.store_b_is_lower (port) then do; /* Store a lower */
		     store_a_index = port;		/* Set scas indexes */
		     store_b_index = port + 8;
		end;
		else do;				/* Memory upside down */
		     store_a_index = port + 8;
		     store_b_index = port;
		end;

		mem = letter (port);

		if scs$controller_data.store_a_online (port) then /* Check all stores */
		     call check_store ("a", store_a_index);
		if scs$controller_data.store_a1_online (port) then
		     call check_store ("a1", store_a_index + 16);
		if scs$controller_data.store_b_online (port) then
		     call check_store ("b", store_b_index);
		if scs$controller_data.store_b1_online (port) then
		     call check_store ("b1", store_b_index + 16);

	     end;

	end;

	if poll_entry then call reschedule;		/* Must schedule next pass */
	if ^stacq (scs$reconfig_lock, "0"b, pds$processid) then
	     call syserr (ANNOUNCE, "mos_memory_check: Lock error.");
	return;

/* Enter here from pxss for polling */

poll: entry;

	if tc_data$mos_polling_interval = 0 then do;	/* Polling was turned off */
	     tc_data$mos_polling_time = never;
	     return;
	end;
	poll_entry = "1"b;
	go to start;


/* Entry to set the polling interval */

set_poll_time: entry (arg_time);

	time = arg_time;
	if time < 0 then do;			/* Request to return time */
	     arg_time = tc_data$mos_polling_interval;
	     return;
	end;
	tc_data$mos_polling_interval = time;
	call syserr (JUST_LOG, "mos_memory_check: MOS polling ^[disabled^;time ^d minute^[s^]^].",
	     (time = 0), time, (time ^= 1));
	call reschedule;
	return;


/* Procedure that will check one store of one memory */

check_store: proc (store_name, scas_index);

dcl  store_name char (2);				/* Name of store being tested */
dcl  scas_index fixed bin (5);			/* Index in scas for pmut$rscr */
dcl  id bit (4) aligned;

	call privileged_mode_ut$rscr (scas_index, (SC_SU), rscr_result); /* Read maintence register */
	if ^poll_entry then do;			/* Called thru gate, so must return data */
	     arg_mem (scas_index) = mem;
	     arg_store (scas_index) = store_name;
	     arg_data (scas_index) = rscr_result;
	end;

	id = scr_su.identification;			/* copy id for easier access */
	if (id = "0011"b) | (id = "0100"b) | (id = "1010"b)
	     | (id = "1011"b) | (id = "1110"b) | (id = "1111"b) then do; /* MOS memory */
	     if scr_su.syndrome ^= "0"b then do;	/* Some error occured */
		if spoke (scas_index) then aloud = JUST_LOG; else aloud = ANNOUNCE; /* Mild fuss first time */
		spoke (scas_index) = "1"b;
		call syserr$binary (aloud, scrp, SB_mos_err, SBL_mos_err,
		     "mos_memory_check: EDAC error on mem ^a store ^a.", mem, store_name);
	     end;
	end;
	return;

     end check_store;

/* Procedure to calculate the next time to poll */

reschedule: proc;

	if tc_data$mos_polling_interval = 0 then tc_data$mos_polling_time = never;
	else tc_data$mos_polling_time = clock_ () + 60000000 * tc_data$mos_polling_interval;

	return;

     end reschedule;


clean_up: proc;

dcl  ignore bit (1);

	ignore = stacq (scs$reconfig_lock, "0"b, pds$processid); /* Unlock if I locked it */
	return;

     end clean_up;
						/* format: off */
%page; %include syserr_constants;
%page; %include syserr_binary_def;
%page; %include scr;
%page; %include scs;
%page;
/* BEGIN MESSAGE DOCUMENTATION

   Message:
   mos_memory_check: Lock error.

   S:	$info

   T:	$run

   M:	After checking the memory controllers for errors,
   the program mos_memory check attempted to unlock the reconfiguration lock
   and found it unlocked.
   The system continues to run.

   A:	$ignore


   Message:
   mos_memory_check: MOS polling disabled

   S:	$log

   T:	$run

   M:	A system administrator has disabled MOS memory polling.

   A:	$ignore


   Message:
   mos_memory_check: MOS polling time NN minutes.

   S:	$log

   T:	$run

   M:	A system administrator has set the MOS memory polling time to NN minutes.

   A:	$ignore


   Message:
   mos_memory_check: EDAC error on mem X store Y.

   S:	$warn

   T:	$run

   M:	MOS memory polling has found that
   the maintenance register in the system controller
   shows a nonzero syndrome.
   The data is logged for use by HEALS or mos_edac_summary.
   Only the first occurrence of this error is printed online for each box.

   A:	$ignore


   END MESSAGE DOCUMENTATION */

     end mos_memory_check;
  



		    syserr_copy_wired_log.pl1       11/11/89  1139.4rew 11/11/89  0839.1       83970



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1984 *
        *                                                         *
        *********************************************************** */
/* format: style2,indcomtxt */

syserr_copy_wired_log:
     procedure;

/**** This procedure copies all the messages from the wired buffer
      to the paged syserr log partition.

      It is called by the SyserrLogger the Hproc.

      This procedure expects to be called unwired, with neither the
      paged log lock nor the wired log lock held.

      1) It locks the paged log.

      2) It wires down.

      3) It locks the wired log (a spin lock)

      4) It copies the wired buffer and marks it empty.

      5) It unlocks the wired log.

      6) It unwires and unmasks.

      7) It calls syserr_copy to actually put the text from
      the copy of the wired buffer into the paged log.

      8) It unlocks the paged log and returns.

      NOTE
      This would be considerably more robust if syserr_copy
      were able to copy directly into the paged log from the
      wired log, by temp-wiring the neccessary pages of paged log,
      copying, and then unwiring. The wired buffer should not
      be marked AVAILABLE until the messages have been successfully
      disposed of.
*/

/**** History
      Created 1984-11-26 BIM: from syserr_log_daemon of Sibert.
      Modified 1985-01-25 Keith Loepere: fix race in syserr_real copying.
      Modified 1985-02-19 Keith Loepere: for making the paged syserr lock
      the highest paged lock.
      Modified 1985-03-08 EJ Sharpe: added adjust_wired_log_sequence
*/
%page;

	declare P_sequence_increment	 fixed bin (35) parameter;

	declare automatic_buffer	 (syserr_data$wired_log_size) bit (36) aligned automatic;
	declare based_buffer	 (syserr_data$wired_log_size) bit (36) aligned based;

	declare msg_idx		 fixed bin;
	declare sequence_increment	 fixed bin (35);	/* arg copy */
	declare temp_mask		 bit (72) aligned;	/* global since it is unwise to call unwire_unmask in a condition handler */
	declare wire_arg		 fixed bin (71);
	declare wire_ptr		 pointer;

	declare pmut$read_mask	 entry (bit (72) aligned);
	declare pmut$wire_and_mask	 entry (fixed bin (71), pointer);
	declare pmut$unwire_unmask	 entry (fixed bin (71), pointer);
	declare syserr		 entry options (variable);
	declare syserr_copy$lock	 entry ();
	declare syserr_copy$unlock	 entry ();
	declare syserr_copy$wired_log	 entry (pointer);

	declare pds$processid	 bit (36) external aligned;
	declare syserr_data$wired_log_size
				 external fixed bin (35);
	declare scs$sys_level	 bit (72) aligned external;

	declare any_other		 condition;

	declare (addr, null, rel, stacq, unspec)
				 builtin;
%page;
	syserr_log_data_ptr = addr (syserr_log_data$);
	sd_ptr = addr (syserr_data$syserr_area);
	wlog_ptr = addr (syserr_data$wired_log_area);

	call syserr_copy$lock ();			/* Lock the paged log */

	call pmut$wire_and_mask (wire_arg, wire_ptr);

	call get_wired_log ();

	call pmut$unwire_unmask (wire_arg, wire_ptr);	/* Permit faults to occur and be handled */

	on any_other call condition_handler;

	call syserr_copy$wired_log (addr (automatic_buffer));

	if syserr_log_data.take_a_fault
	then do;					/* For use to test fault recovery: patch this bit on */
		syserr_log_data.take_a_fault = "0"b;	/* and get a fault. Turn it off, of course, since we */
		null () -> syserr_log_data.take_a_fault = "0"b;
						/* only want one fault at a time */
	     end;

	revert any_other;

	call syserr_copy$unlock ();			/* Unlock the paged log */
	return;

RETURN_ERROR:
	if (syserr_log_data.lock.pid = pds$processid)
	then call syserr_copy$unlock ();

	if temp_mask = scs$sys_level
	then call pmut$unwire_unmask (wire_arg, wire_ptr);

	if (syserr_log_data.error_count > 5) & sd.log_flag
	then do;					/* We turn off logging after five errors */
		call syserr (BEEP, "syserr_copy_wired_log: Too many faults: log copying will be disabled.");
		sd.log_flag = "0"b;			/* to avoid getting into a loop doing this */
	     end;
	syserr_log_data.error_count = syserr_log_data.error_count + 1;

	return;
%page;

/* The following entrypoint is called from syserr_seg_manager during
   answering service initialization.  The task is to increase all sequence
   numbers in the wired log by the value supplied.   This is to get the paged
   and wired log messages consistant with what the AS has found in the syserr
   log history (i.e. the permanent log segments). */

adjust_wired_log_sequence:
     entry (P_sequence_increment);

	sequence_increment = P_sequence_increment;
	sd_ptr = addr (syserr_data$syserr_area);
	wlog_ptr = addr (syserr_data$wired_log_area);

	call pmut$wire_and_mask (wire_arg, wire_ptr);

	if (sd.lock = pds$processid)
	then call lock_error ();

	do while (^stacq (sd.lock, pds$processid, ""b));
	end;

	wlog.seq_num = wlog.seq_num + sequence_increment; /* make sure next incoming message will be right */

	wmess_ptr = addr (wlog.buffer);		/* first message */

	do msg_idx = 1 to wlog.head.count;
	     wmess.seq_num = wmess.seq_num + sequence_increment;
	     wmess_ptr = addrel (wmess_ptr, currentsize (wmess));
						/* Move on to the next message */
	end;

	if ^stacq (sd.lock, ""b, pds$processid)
	then call lock_error ();

	call pmut$unwire_unmask (wire_arg, wire_ptr);

	return;
%page;

get_wired_log:
     procedure ();

	declare message_count	 fixed bin;

/* This procedure copies the contents of the wired log into our buffer in automatic
   storage (also wired, at the moment).	 It locks the wired log, copies the message(s),
   resets the wired log to say that it's now empty, unlocks the wired log, and
   returns.  Once we unlock, the next message will be put at the top of the wired
   buffer.  If we can do all of this before the wired buffer is full, we will never
   lose any messages. */


	if (sd.lock = pds$processid)
	then /* MYLOCK error */
	     call lock_error ();

	do while (^stacq (sd.lock, pds$processid, ""b));
	end;

/* We will copy the whole wired log buffer plus its extension into our own buffer. */

	unspec (automatic_buffer) = unspec (wlog_ptr -> based_buffer);

	message_count = wlog.count;			/* Save for metering */

/* This is where a call to meter_oc_log_ used to be made, but it was removed
   because meter_oc_log_ is so silly, and because there isn't anything to
   extract the meters, anyway. Real metering ought to be added back someday. */

	wlog.next = rel (addr (wlog.buffer));		/* Start next message at top of buffer. */
	wlog.count = 0;				/* No entries in buffer now. */

	if ^stacq (sd.lock, ""b, pds$processid)
	then call lock_error ();

	return;
     end get_wired_log;


lock_error:
     procedure ();

/* This procedure crashes the system when a locking error occurs on the
   wired syserr data lock-- but first, it turns off logging just in case
   it gets restarted or other messages are generated before the crash. */

	sd.log_flag = "0"b;
	call syserr (CRASH, "syserr_copy_wired_log: Bad syserr_data lock ^w.", sd.lock);

	return;
     end lock_error;

condition_handler:
     procedure ();

	declare severity		 fixed bin;
	declare buf_ptr		 pointer;
	declare mess_ptr		 pointer;

	call pmut$read_mask (temp_mask);
	if temp_mask = scs$sys_level
	then /* If we took a fault while wired, we should have */
	     severity = CRASH;			/* crashed already (fim detects this), but just in case... */
	else severity = BEEP;

	buf_ptr = addr (automatic_buffer);
	mess_ptr = addr (buf_ptr -> wlog.buffer);

	call syserr (severity,
	     "syserr_copy_wired_log: Fault occurred while copying into LOG partition. Messages ^d to ^d may be lost",
	     mess_ptr -> wmess.seq_num, buf_ptr -> wlog.head.seq_num);

	go to RETURN_ERROR;				/* main line uses temp_mask to decide to unwire. */
     end condition_handler;

%page;
%include syserr_data;
%page;
%include syserr_log_dcls;
%page;
%include syserr_constants;
%page;
/* BEGIN MESSAGE DOCUMENTATION

   Message:
   syserr_copy_wired_log: Bad lock WWWWWWWWWWWW at SSS|OOOOOO

   S:	$crash

   T:	$run

   M:	$err
   The contents of the lock word and its address are printed, as an aid
   for debugging.

   A:	$recover

   Message:
   syserr_copy_wired_log: Fault occurred while copying into LOG partition. Messages NNNN to NNNN may be lost.

   S:	$crash

   T:	$run

   M:	$err
   A fault has occurred while copying data from the wired syserr log buffer
   to the paged syserr log. This
   usually results from a disk error on the LOG partition, which would
   also generate disk error messages.  The sequence numbers of the
   affected messages are given because those messages may not appear
   in the LOG partition.

   A:	$recover


   Message:
   syserr_copy_wired_log: Too many faults, log copying disabled.

   S:	$beep

   T:	$run

   M:	$err
   If too many errors occur updating the LOG partition, log copying will
   be disabled, which causes all further messages to be printed on the
   console but not entered in the log.

   A:	$notify

   END MESSAGE DOCUMENTATION */

     end syserr_copy_wired_log;
  



		    syserr_log_daemon.pl1           11/11/89  1139.4rew 11/11/89  0839.1       33408



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1984 *
        *                                                         *
        *********************************************************** */
syserr_log_daemon:
     procedure ();

/* *	SYSERR_LOG_DAEMON
   *
   *	This is the procedure always run by the SyserrLogger.SysDaemon HPROC.
   *	It deals with copying between the wired syserr buffer and the log
   *	segments in the paged LOG partition.  It is called once when the 
   *	syserr daemon is created, and never returns.  It is one of the 
   *	few programs in the system to go blocked in ring zero. It sets up
   *	some automatic variables and then enters a block loop awaiting wakeups
   *	indicating that there may be something in the wired buffer to copy out
   *	into the paged log. It should be run only by the syserr logger HPROC.
   *
   *	Modification history:
   *	73-10-05, Bill Silver: Initial coding
   *	74-06-09, Bill Silver: Added copy entry
   *	74-11-12, Lee Scheffler: Log copying added
   *	75-11-15, Larry Johnson: Moved most of the code in this module to
   *	   a non-wired procedure (syserr_copy_paged)
   *	76-01-10, Larry Johnson: Modified to lock paged syserr log
   *	76-03-22, Steve Webber: Modified to use logger HPROC
   *	79-05-03, Mike Grady: Modified for ring 0 stack sharing-- hproc has
   *	   own stack and pxss$block now has no args.
   *	84-08-24, W. Olin Sibert: Reorganized for new syserr log mechanism:
   *	   use pmut$wire_and_mask instead of options (validate), use
   *	   syserr_log_data for locking, handle conditions and restart, change
   *	   name from syserr_logger to syserr_log_daemon.
   *    1984-11-26, BIM: moved the guts of this to syserr_copy_wired_log,
		which can be called outside the Daemon.
   *    1985-01-25, Keith Loepere, to fix race in async log copying.
   *	85-02-19, Keith Loepere, for making the paged syserr log the 
		highest paged lock.
   */

	declare wire_arg		 bit (72) aligned;
	declare wire_ptr		 pointer;

	declare pmut$wire_and_mask	 entry (bit (72) aligned, pointer);
	declare pmut$unwire_unmask	 entry (bit (72) aligned, pointer);
	declare pxss$block		 entry;
	declare syserr_copy_wired_log	 entry;

	declare addr		 builtin;

/* */

	syserr_log_data_ptr = addr (syserr_log_data$);
	sd_ptr = addr (syserr_data$syserr_area);
	wlog_ptr = addr (syserr_data$wired_log_area);

/* This process remains wired and masked for all its life EXCEPT when it is
   actually putting messages into the paged log (which it has already extracted
   from the wired log).  This is done in order to reduce the possibility that
   it will be unable to operate; essentially, it eliminates all but the pages
   of the paged log itself from consideration as sources of error.  This is
   not entirely true, since the stack is unwired whilst calling. */

LOGGER_LOOP:
	call pmut$wire_and_mask (wire_arg, wire_ptr);

	do while ("1"b);
	     if ^syserr_log_data.test_mode then do;
		     call pxss$block ();		/* wait for something to happen */
		end;
	     call pmut$unwire_unmask (wire_arg, wire_ptr);/* Permit faults to occur and be handled */

	     call syserr_copy_wired_log;

	     call pmut$wire_and_mask (wire_arg, wire_ptr);/* Turn faults off again */

	     if syserr_log_data.test_mode then
		return;
	end;

/* */


/* */


%page; %include syserr_data;
%page; %include syserr_log_dcls;
%page; %include syserr_constants;

     end syserr_log_daemon;



		    bull_copyright_notice.txt       08/30/05  1008.4r   08/30/05  1007.3    00020025

                                          -----------------------------------------------------------


Historical Background

This edition of the Multics software materials and documentation is provided and donated
to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. 
as a contribution to computer science knowledge.  
This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology,
Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull
and Bull HN Information Systems Inc. to the development of this operating system. 
Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970),
renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership
of Professor Fernando Jose Corbato.Users consider that Multics provided the best software architecture for 
managing computer hardware properly and for executing programs. Many subsequent operating systems
incorporated Multics principles.
Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., 
as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. .

                                          -----------------------------------------------------------

Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without
fee is hereby granted,provided that the below copyright notice and historical background appear in all copies
and that both the copyright notice and historical background and this permission notice appear in supporting
documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining
to distribution of the programs without specific prior written permission.
    Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc.
    Copyright 2006 by Bull HN Information Systems Inc.
    Copyright 2006 by Bull SAS
    All Rights Reserved

