Subsections

- Floating-point unit control
- Terminating a process
- Garbage-collector control

# Control routines

Three groups of procedures and operators are provided to control various aspects of the run-time environment. These are floating-point control, process termination control and garbage-collector control.

## Floating-point unit control

The Intel Pentium microprocessors all have a floating-point unit (FPU) as an integral part of the microprocessor. The action of the FPU is determined by the contents of a 16-bit register called the “control word register”. Details of the register can be found in the file

       /usr/include/fpu_control.h

Details of the working of the FPU, as controlled by the control word register can be found in the three volumes of the Intel Architecture Software Developer's Manual. The control word contains bits which control rounding, precision and whether floating-point errors should cause an exception.

The QAD standard prelude provides two integers which control the rounding method. They are

1. `fe to nearest`
2. `fe downward`.

The `spaliens.a68` file also has three procedures which give access to two C functions.

1. `fe set round` with header `PROC(INT)INT` which is used with the two integers aforementioned.
2. `fe get round` which has mode `PROC INT`.
3. `lrint` which has mode `PROC(REAL)INT` and gives access to the C function of the same name.

Here is the source code (in `spops.a68`) for the operator `ROUND`:-

       OP ROUND = (REAL r)INT:
       IF r > max int OR r < -max int
       THEN 0
       ELSE
          INT method=fe get round;
          fe set round(fe tonearest);
          INT i=lrint(r);
          fe set round(method);
          i
       FI; #ROUND#

Notice how the FPU control word is reset to its original value before the end of the operator.

The FPU control word is also used to control whether overflow should be detectable. The standard mode of operation is to ignore integer overflow. The procedure to trap a signal (`on signal`) is declared as follows:-

       PROC on signal=(INT sig,
                       PROC(INT)VOID handler)VOID:

The example program `testov.a68` shows how `on signal` can be used. The Algol 68 identifiers for all the Linux signals are the same as the Linux signal identifiers, but in lower case. For example, the signal used in FPU control is `sigfpu`. The signal generated by keying `Ctrl-C` (sometimes depicted as `^C`) on program input is `sigint`. Here is a short program which illustrates signal trapping:-

       PROGRAM sig CONTEXT VOID
       USE standard
       BEGIN
          on signal(sigint,
                    (INT sig)VOID:
                     (write(("sigint trapped",
                             newline));
                      exit(1)));
          write("Please key ^C: "); read(LOC CHAR);
          write(("No signal trapped",newline))
       END
       FINISH

Usually, when you trap a signal such as `sigint`, your program could close down processing in an orderly manner: files could be closed properly, a message to the user could be issued, and so on. You can do anything you want in the procedure provided as a parameter to `on signal`. You can also predeclare the procedure and simply provide its identifier in the `on signal` call.

Integer overflow is ignored by the microprocessor. So the formula `max int + 3` simply yields an incorrect value.

The procedure `ansi raise` will cause any specified signal to occur. Here is the mode of `ansi raise`:

       PROC ansi raise = (INT sig)INT:

## Terminating a process

As well as raising and trapping signals, it is sometimes useful to specify procedures to be elaborated when your program has finished, for whatever reason. Four procedures are provided for process termination:-

1. `PROC iso at exit=(PROC VOID p)INT:`
   The procedure `p` is registered to be elaborated when the program terminates normally or when the procedure `exit` (see procedure 3) is called. Registered procedures are elaborated in the reverse order of being registered, so that the procedure registered last is elaborated first. The procedure `at exit` yields 0 for success, -1 for an error.
2. `PROC on exit=(PROC(INT,CPTR)VOID p,`
   `[]CHAR arg)INT:`
   Unlike the procedure `at exit` (see above), `on exit` allows you to register a procedure which takes two parameters. The first is the integer parameter given to the `exit` procedure (or 0 for normal termination) and the second is a `[]CHAR` which the procedure `p` can use. `on exit` yields 0 for success and -1 for an error.
3. `PROC exit = (INT status)VOID:`
   This procedure terminates the program immediately. Any procedures registered using `at exit` or `on exit` will be elaborated in the reverse order of registration. Any open files will be closed, but Algol 68 buffers will not be flushed. The value of `status` will be passed to the parent process of the program.
4. `PROC stop = VOID:`
   This is a synonym for `exit(0)`.

The example program `testexit.a68` shows one way in which `at exit` and `on exit` may be used.

## Garbage-collector control

The garbage-collector manages the run-time heap. The term “garbage” is used to designate memory on the heap which is no longer referenced. Although the garbage-collector is usually called whenever space on the heap is required, a number of routines are provided for explicit garbage collection or for fine control of the garbage-collector.

1. `PROC garbage_collect = VOID:`
   The garbage-collector can be called explicitly by an Algol 68 program using this procedure.
2. `PROC disable_garbage_collector = VOID:`
   Disables the garbage-collector.
3. `PROC enable_garbage_collector = VOID:`
   Enables the garbage-collector.
4. `PROC gc_param = (VECTOR[]CHAR cmd,INT v)INT:`
   This routine is used to set or get the values of a number of parameters which control the garbage-collector. The `cmd` should consist of `GET` or `SET` followed by the string identifying the required parameter followed by a `nul ch`. The available strings are
   1. `COLLECTION THRESHOLD` The number of bytes in use before the next garbage collection is allowed.
   2. `HEAP INCREMENT` The number of bytes by which the heap should be increased in size whenever the heap is grown.
   3. `MAX HEAP SIZE` The maximum size of the heap in bytes.
   4. `MIN HEAP SIZE` The minimum size of the heap in bytes.
   5. `MAX SEGMENT SIZE` The maximum size of a memory segment acquired for the heap.
   6. `MIN SEGMENT SIZE` The minimum size of a memory segment acquired for the heap.
   7. `POLICY` The heap policy. Three values are provided for setting the heap policy:-
      1. `INT always collect`
         The garbage-collector will always be called if space is required.
      2. `INT always grow heap`
         The garbage-collector will never be called even if space is required.
      3. `INT default policy`
         The garbage-collector will be called if there is insufficient space in the heap for the memory required. Extra space will be acquired if garbage-collection does not yield the spaced needed.
      Whether the heap is grown or whether garbage-collection takes place depends on the current policy which is usually specified by the environment string `A68_GC_POLICY`.
5. `PROC get_gc_param = (VECTOR[]CHAR param)INT:`
   Gets the current value of the garbage-collector parameter (any one of the strings given in this section).
6. `PROC set_gc_params = (VECTOR[]GCPARAM gcpar)VOID:`
   Sets the value of the garbage-collector parameter (any one of the strings given in this section).

For further details about the garbage-collector, consult the code in the `library` directory in the a68toc source tree.