aboutsummaryrefslogblamecommitdiffstats
path: root/erts/emulator/beam/erl_monitors.h
blob: 1cacecd7e9d564a29a31525ab7d36fd4eccedd2b (plain) (tree)
1
2
3
4
5


                   
                                                        
   










                                                                           



































































                                                                               


                         






                                                                             
                                                                      












                                                                        
                                                                                  
              






                                                                               




























                                                                       




                                            
                                                                             


























                                                                                 

                                                    





                                                                  
/*
 * %CopyrightBegin%
 * 
 * Copyright Ericsson AB 2004-2017. All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * %CopyrightEnd%
 */

/**********************************************************************
 * Header for monitors and links data structures.
 * Monitors are kept in an AVL tree and the data structures for
 * the four different types of monitors are like this:
 **********************************************************************
 * Local monitor by pid/port: 
 * (Ref is always same in all involved data structures)
 **********************************************************************
 *        Process/Port X     Process Y
 *       +-------------+    +-------------+
 * Type: | MON_ORIGIN  |    | MON_TARGET  |
 *       +-------------+    +-------------+
 * Pid:  | Pid(Y)      |    | Pid/Port(X) |
 *       +-------------+    +-------------+
 * Name: | []          |    | []          |
 *       +-------------+    +-------------+
 **********************************************************************
 * Local monitor by name: (Ref is always same in all involved data structures)
 **********************************************************************
 *        Process X          Process Y (name foo)
 *       +-------------+    +-------------+
 * Type: | MON_ORIGIN  |    | MON_TARGET  |
 *       +-------------+    +-------------+
 * Pid:  | Pid(Y)      |    | Pid(X)      |
 *       +-------------+    +-------------+
 * Name: | Atom(foo)   |    | Atom(foo)   |
 *       +-------------+    +-------------+
 **********************************************************************
 * Remote monitor by pid: (Ref is always same in all involved data structures)
 **********************************************************************
 *                    Node A              |           Node B
 *       ---------------------------------+----------------------------------
 *        Process X (@A)   Distentry @A       Distentry @B     Process Y (@B)
 *                         for node B         for node A 
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * Type: | MON_ORIGIN  |  | MON_TARGET  |    | MON_ORIGIN  |  | MON_TARGET  |
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * Pid:  | Pid(Y)      |  | Pid(X)      |    | Pid(Y)      |  | Pid(X)      |
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * Name: | []          |  | []          |    | []          |  | []          |
 *       +-------------+  +-------------+    +-------------+  +-------------+
 **********************************************************************
 * Remote monitor by name: (Ref is always same in all involved data structures)
 **********************************************************************
 *                    Node A              |           Node B
 *       ---------------------------------+----------------------------------
 *        Process X (@A)   Distentry @A       Distentry @B     Process Y (@B)
 *                         for node B         for node A       (name foo)
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * Type: | MON_ORIGIN  |  | MON_TARGET  |    | MON_ORIGIN  |  | MON_TARGET  |
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * Pid:  | Atom(node B)|  | Pid(X)      |    | Pid(Y)      |  | Pid(X)      |
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * Name: | Atom(foo)   |  | Atom(foo)   |    | Atom(foo)   |  | Atom(foo)   |
 *       +-------------+  +-------------+    +-------------+  +-------------+
 * The reason for the node atom in X->pid is that we don't know the actual
 * pid of the monitored process on the other node when setting the monitor
 * (which is done asyncronously).
 **********************************************************************/
#ifndef _ERL_MONITORS_H
#define _ERL_MONITORS_H

/* Type tags for monitors */
#define MON_ORIGIN 1
#define MON_TARGET 2
#define MON_NIF_TARGET 3
#define MON_TIME_OFFSET 4

/* Type tags for links */
#define LINK_PID 1   /* ...Or port */
#define LINK_NODE 3  /* "Node monitor" */  

/* Size of a monitor without heap, in words (fixalloc) */
#define ERTS_MONITOR_SIZE ((sizeof(ErtsMonitor) - sizeof(Uint))/sizeof(Uint))
#define ERTS_MONITOR_SH_SIZE (ERTS_MONITOR_SIZE + ERTS_REF_THING_SIZE)
#define ERTS_LINK_SIZE ((sizeof(ErtsLink) - sizeof(Uint))/sizeof(Uint))
#define ERTS_LINK_SH_SIZE ERTS_LINK_SIZE /* Size of fix-alloced links */

/* ErtsMonitor and ErtsLink *need* to begin in a similar way as 
   ErtsMonitorOrLink */
typedef struct erts_monitor_or_link {
    struct erts_monitor_or_link *left, *right;
    Sint16 balance;    
} ErtsMonitorOrLink;

typedef struct erts_monitor {
    struct erts_monitor *left, *right; 
    Sint16 balance;
    Uint16 type;  /* MON_ORIGIN | MON_TARGET | MON_NIF_TARGET | MON_TIME_OFFSET */
    Eterm ref;
    union {
        Eterm pid;  /* In case of distributed named monitor, this is the
		     * nodename atom in MON_ORIGIN process, otherwise a pid or,
		     * in case of a MON_TARGET, a port
                     */
        struct ErtsResource_* resource; /* MON_NIF_TARGET */
    }u;
    Eterm name;   /* When monitoring a named process: atom() else [] */
    Uint heap[1]; /* Larger in reality */
} ErtsMonitor;

typedef struct erts_link {
    struct erts_link *left, *right;
    Sint16 balance;
    Uint16 type;             /* LINK_PID | LINK_NODE */
    Eterm pid;               /* When node monitor, 
				the node atom is here instead */
    union {
	struct erts_link *root;  /* Used only in dist entries */
	Uint refc;
    } shared;
    Uint heap[1];            /* Larger in reality */
} ErtsLink;   

typedef struct erts_suspend_monitor {
    struct erts_suspend_monitor *left, *right;
    Sint16 balance;

    int pending;
    int active;
    Eterm pid;
} ErtsSuspendMonitor;

#define ERTS_LINK_ROOT(Linkp) ((Linkp)->shared.root)
#define ERTS_LINK_REFC(Linkp) ((Linkp)->shared.refc) 

Uint erts_tot_link_lh_size(void);


/* Prototypes */
void erts_destroy_monitor(ErtsMonitor *mon);
void erts_add_monitor(ErtsMonitor **root, Uint type, Eterm ref, UWord entity,
		      Eterm name);
ErtsMonitor *erts_remove_monitor(ErtsMonitor **root, Eterm ref);
ErtsMonitor *erts_lookup_monitor(ErtsMonitor *root, Eterm ref);
void erts_sweep_monitors(ErtsMonitor *root, 
			 void (*doit)(ErtsMonitor *, void *),
			 void *context);

void erts_destroy_link(ErtsLink *lnk);
/* Returns 0 if OK, < 0 if already present */
int erts_add_link(ErtsLink **root, Uint type, Eterm pid);
ErtsLink *erts_add_or_lookup_link(ErtsLink **root, Uint type, Eterm pid);
ErtsLink *erts_remove_link(ErtsLink **root, Eterm pid);
ErtsLink *erts_lookup_link(ErtsLink *root, Eterm pid);
void erts_sweep_links(ErtsLink *root, 
		      void (*doit)(ErtsLink *, void *),
		      void *context);

void erts_destroy_suspend_monitor(ErtsSuspendMonitor *sproc);
void erts_sweep_suspend_monitors(ErtsSuspendMonitor *root,
				 void (*doit)(ErtsSuspendMonitor *, void *),
				 void *context);
ErtsSuspendMonitor *erts_add_or_lookup_suspend_monitor(ErtsSuspendMonitor **root,
						       Eterm pid);
ErtsSuspendMonitor *erts_lookup_suspend_monitor(ErtsSuspendMonitor *root,
						Eterm pid);
void erts_delete_suspend_monitor(ErtsSuspendMonitor **root, Eterm pid);
void erts_init_monitors(void);
void erts_one_link_size(ErtsLink *lnk, void *vpu);
void erts_one_mon_size(ErtsMonitor *mon, void *vpu);

#define erts_doforall_monitors erts_sweep_monitors
#define erts_doforall_links erts_sweep_links
#define erts_doforall_suspend_monitors erts_sweep_suspend_monitors

#endif /* _ERL_MONITORS_H */