
  -spec erlang:system_monitor(MonitorPid, Options) -> MonSettings
                                 when
                                     MonitorPid :: pid(),
                                     Options :: [system_monitor_option()],
                                     MonSettings ::
                                         undefined |
                                         {OldMonitorPid, OldOptions},
                                     OldMonitorPid :: pid(),
                                     OldOptions ::
                                         [system_monitor_option()].

  Types:
    -type system_monitor_option() ::
          busy_port | busy_dist_port |
          {long_gc, non_neg_integer()} |
          {long_schedule, non_neg_integer()} |
          {large_heap, non_neg_integer()}.

  Sets the system performance monitoring options. MonitorPid is a
  local process identifier (pid) receiving system monitor messages.
  The second argument is a list of monitoring options:

  {long_gc, Time}:
    If a garbage collection in the system takes at least Time
    wall clock milliseconds, a message {monitor, GcPid, long_gc,
    Info} is sent to MonitorPid. GcPid is the pid that was
    garbage collected. Info is a list of two-element tuples
    describing the result of the garbage collection.

    One of the tuples is {timeout, GcTime}, where GcTime is
    the time for the garbage collection in milliseconds. The other
    tuples are tagged with heap_size, heap_block_size, 
    stack_size, mbuf_size, old_heap_size, and 
    old_heap_block_size. These tuples are explained in the
    description of trace message gc_minor_start (see 
    erlang:trace/3). New tuples can be added, and the order of
    the tuples in the Info list can be changed at any time
    without prior notice.

  {long_schedule, Time}:
    If a process or port in the system runs uninterrupted for at
    least Time wall clock milliseconds, a message {monitor,
    PidOrPort, long_schedule, Info} is sent to MonitorPid. 
    PidOrPort is the process or port that was running. Info is
    a list of two-element tuples describing the event.

    If a pid(), the tuples {timeout, Millis}, {in, Location},
    and {out, Location} are present, where Location is either
    an MFA ({Module, Function, Arity}) describing the function
    where the process was scheduled in/out, or the atom undefined.

    If a port(), the tuples {timeout, Millis} and 
    {port_op,Op} are present. Op is one of proc_sig, timeout, 
    input, output, event, or dist_cmd, depending on which
    driver callback was executing.

    proc_sig is an internal operation and is never to appear,
    while the others represent the corresponding driver callbacks 
    timeout, ready_input, ready_output, event, and outputv
    (when the port is used by distribution). Value Millis in
    tuple timeout informs about the uninterrupted execution time
    of the process or port, which always is equal to or higher
    than the Time value supplied when starting the trace. New
    tuples can be added to the Info list in a future release.
    The order of the tuples in the list can be changed at any time
    without prior notice.

    This can be used to detect problems with NIFs or drivers that
    take too long to execute. 1 ms is considered a good maximum
    time for a driver callback or a NIF. However, a time-sharing
    system is usually to consider everything < 100 ms as
    "possible" and fairly "normal". However, longer schedule times
    can indicate swapping or a misbehaving NIF/driver. Misbehaving
    NIFs and drivers can cause bad resource utilization and bad
    overall system performance.

  {large_heap, Size}:
    If a garbage collection in the system results in the allocated
    size of a heap being at least Size words, a message 
    {monitor, GcPid, large_heap, Info} is sent to MonitorPid. 
    GcPid and Info are the same as for long_gc earlier,
    except that the tuple tagged with timeout is not present.

    The monitor message is sent if the sum of the sizes of all
    memory blocks allocated for all heap generations after a
    garbage collection is equal to or higher than Size.

    When a process is killed by max_heap_size, it is killed
    before the garbage collection is complete and thus no large
    heap message is sent.

  busy_port:
    If a process in the system gets suspended because it sends to
    a busy port, a message {monitor, SusPid, busy_port, Port} is
    sent to MonitorPid. SusPid is the pid that got suspended
    when sending to Port.

  busy_dist_port:
    If a process in the system gets suspended because it sends to
    a process on a remote node whose inter-node communication was
    handled by a busy port, a message {monitor, SusPid,
    busy_dist_port, Port} is sent to MonitorPid. SusPid is
    the pid that got suspended when sending through the inter-node
    communication port Port.

  Returns the previous system monitor settings just like 
  erlang:system_monitor/0.

  The arguments to system_monitor/2 specifies how all system
  monitoring on the node should be done, not how it should be
  changed. This means only one process at a time (MonitorPid) can
  be the receiver of system monitor messages. Also, the way to clear
  a specific monitor option is to not include it in the list 
  Options. All system monitoring will, however, be cleared if the
  process identified by MonitorPid terminates.

  There are no special option values (like zero) to clear an option.
  Some of the options have a unspecified minimum value. Lower values
  will be adjusted to the minimum value. For example, it is
  currently not possible to monitor all garbage collections with 
  {long_gc, 0}.

  Note:
    If a monitoring process gets so large that it itself starts to
    cause system monitor messages when garbage collecting, the
    messages enlarge the process message queue and probably make
    the problem worse.

    Keep the monitoring process neat and do not set the system
    monitor limits too tight.

  Failures:

  badarg:
    If MonitorPid does not exist.

  badarg:
    If MonitorPid is not a local process.
