~ubuntu-branches/ubuntu/karmic/erlang/karmic-security

« back to all changes in this revision

Viewing changes to erts/emulator/beam/dist.h

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-06-11 12:18:07 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090611121807-ks7eb4xrt7dsysgx
Tags: 1:13.b.1-dfsg-1
* New upstream release.
* Removed unnecessary dependency of erlang-os-mon on erlang-observer and
  erlang-tools and added missing dependency of erlang-nox on erlang-os-mon
  (closes: #529512).
* Removed a patch to eunit application because the bug was fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#ifndef __DIST_H__
21
21
#define __DIST_H__
22
22
 
 
23
#include "erl_process.h"
 
24
#include "erl_node_tables.h"
 
25
 
23
26
#define DFLAG_PUBLISHED           0x01
24
27
#define DFLAG_ATOM_CACHE          0x02
25
28
#define DFLAG_EXTENDED_REFERENCES 0x04
33
36
#define DFLAG_BIT_BINARIES        0x400
34
37
#define DFLAG_NEW_FLOATS          0x800
35
38
#define DFLAG_UNICODE_IO          0x1000
 
39
#define DFLAG_DIST_HDR_ATOM_CACHE 0x2000
 
40
#define DFLAG_SMALL_ATOM_TAGS     0x4000
36
41
 
37
42
/* All flags that should be enabled when term_to_binary/1 is used. */
38
43
#define TERM_TO_BINARY_DFLAGS (DFLAG_EXTENDED_REFERENCES        \
71
76
extern Export* dexit_trap;
72
77
extern Export* dmonitor_p_trap;
73
78
 
 
79
typedef enum {
 
80
    ERTS_DSP_NO_LOCK,
 
81
    ERTS_DSP_RLOCK,
 
82
    ERTS_DSP_RWLOCK
 
83
} ErtsDSigPrepLock;
 
84
 
 
85
 
74
86
typedef struct {
75
87
    Process *proc;
76
 
    ErtsProcLocks lcks;
77
 
    DistEntry *dep;
78
 
    Port *dprt;
79
 
} ErtsDistOpData;
80
 
 
81
 
#define ERTS_DIST_OP_DATA_INIT(DODP, PROC, LCKS, DEP, DPRT)     \
82
 
do {                                                            \
83
 
    (DODP)->proc = (PROC);                                      \
84
 
    (DODP)->lcks = (LCKS);                                      \
85
 
    (DODP)->dep = (DEP);                                        \
86
 
    (DODP)->dprt = (DPRT);                                      \
87
 
} while (0)
88
 
 
89
 
ERTS_GLB_INLINE void erts_dist_op_prepare(ErtsDistOpData *,
90
 
                                          DistEntry *,
91
 
                                          Process *,
92
 
                                          ErtsProcLocks);
93
 
ERTS_GLB_INLINE void erts_dist_op_finalize(ErtsDistOpData *);
94
 
 
95
 
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
96
 
 
97
 
ERTS_GLB_INLINE void
98
 
erts_dist_op_prepare(ErtsDistOpData *dodp,
99
 
                     DistEntry *dep,
100
 
                     Process *proc,
101
 
                     ErtsProcLocks proc_locks)
102
 
{
103
 
    Port *dprt;
104
 
    erts_smp_dist_entry_lock(dep);
105
 
#ifdef ERTS_SMP
106
 
    dprt = erts_de2port(dep, proc, proc_locks);
107
 
#else
108
 
    dprt = erts_id2port(dep->cid, NULL, 0);
109
 
#endif
110
 
    ERTS_DIST_OP_DATA_INIT(dodp, proc, proc_locks, dep, dprt);
111
 
}
112
 
 
113
 
ERTS_GLB_INLINE void
114
 
erts_dist_op_finalize(ErtsDistOpData *dodp)
115
 
{
116
 
    if (dodp->dprt)
117
 
        erts_port_release(dodp->dprt);
118
 
    erts_smp_dist_entry_unlock(dodp->dep);
119
 
}
120
 
 
121
 
#endif
122
 
 
123
 
extern int erts_dist_link(ErtsDistOpData *, Eterm, Eterm);
124
 
extern int erts_dist_send(ErtsDistOpData *, Eterm, Eterm);
125
 
extern int erts_dist_exit_tt(ErtsDistOpData *, Eterm, Eterm, Eterm, Eterm);
126
 
extern int erts_dist_unlink(ErtsDistOpData *, Eterm, Eterm);
127
 
extern int erts_dist_reg_send(ErtsDistOpData *, Eterm, Eterm);
128
 
extern int erts_dist_group_leader(ErtsDistOpData *, Eterm, Eterm);
129
 
extern int erts_dist_exit(ErtsDistOpData *, Eterm, Eterm, Eterm);
130
 
extern int erts_dist_exit2(ErtsDistOpData *, Eterm, Eterm, Eterm);
131
 
extern int erts_dist_demonitor(ErtsDistOpData *, Eterm, Eterm, Eterm, int);
132
 
extern int erts_dist_monitor(ErtsDistOpData *, Eterm, Eterm, Eterm);
133
 
extern int erts_dist_m_exit(ErtsDistOpData *, Eterm, Eterm, Eterm, Eterm);
 
88
    DistEntry *dep;
 
89
    Eterm cid;
 
90
    Eterm connection_id;
 
91
    int no_suspend;
 
92
} ErtsDSigData;
 
93
 
 
94
#define ERTS_DE_IS_NOT_CONNECTED(DEP) \
 
95
  (ERTS_SMP_LC_ASSERT(erts_lc_rwmtx_is_rlocked(&(DEP)->rwmtx) \
 
96
                      || erts_lc_rwmtx_is_rwlocked(&(DEP)->rwmtx)), \
 
97
   (is_nil((DEP)->cid) || ((DEP)->status & ERTS_DE_SFLG_EXITING)))
 
98
 
 
99
#define ERTS_DE_IS_CONNECTED(DEP) \
 
100
  (!ERTS_DE_IS_NOT_CONNECTED((DEP)))
 
101
 
 
102
 
 
103
extern int erts_is_alive;
 
104
 
 
105
/*
 
106
 * erts_dsig_prepare() prepares a send of a distributed signal.
 
107
 * One of the values defined below are returned. If the returned
 
108
 * value is another than ERTS_DSIG_PREP_CONNECTED, the
 
109
 * distributed signal cannot be sent before apropriate actions
 
110
 * have been taken. Apropriate actions would typically be setting
 
111
 * up the connection.
 
112
 */
 
113
 
 
114
/* Connected; signal can be sent. */
 
115
#define ERTS_DSIG_PREP_CONNECTED        0
 
116
/* Not connected; connection needs to be set up. */
 
117
#define ERTS_DSIG_PREP_NOT_CONNECTED    1
 
118
/* Caller would be suspended on send operation. */
 
119
#define ERTS_DSIG_PREP_WOULD_SUSPEND    2
 
120
/* System not alive (distributed) */
 
121
#define ERTS_DSIG_PREP_NOT_ALIVE        3
 
122
 
 
123
ERTS_GLB_INLINE int erts_dsig_prepare(ErtsDSigData *,
 
124
                                      DistEntry *,
 
125
                                      Process *,
 
126
                                      ErtsDSigPrepLock,
 
127
                                      int);
 
128
 
 
129
ERTS_GLB_INLINE
 
130
void erts_schedule_dist_command(Port *, DistEntry *);
 
131
 
 
132
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
 
133
 
 
134
ERTS_GLB_INLINE int 
 
135
erts_dsig_prepare(ErtsDSigData *dsdp,
 
136
                  DistEntry *dep,
 
137
                  Process *proc,
 
138
                  ErtsDSigPrepLock dspl,
 
139
                  int no_suspend)
 
140
{
 
141
    int failure;
 
142
    if (!erts_is_alive)
 
143
        return ERTS_DSIG_PREP_NOT_ALIVE;
 
144
    if (!dep)
 
145
        return ERTS_DSIG_PREP_NOT_CONNECTED;
 
146
    if (dspl == ERTS_DSP_RWLOCK)
 
147
        erts_smp_de_rwlock(dep);
 
148
    else
 
149
        erts_smp_de_rlock(dep);
 
150
    if (ERTS_DE_IS_NOT_CONNECTED(dep)) {
 
151
        failure = ERTS_DSIG_PREP_NOT_CONNECTED;
 
152
        goto fail;
 
153
    }
 
154
    if (no_suspend) {
 
155
        failure = ERTS_DSIG_PREP_CONNECTED;
 
156
        erts_smp_spin_lock(&dep->qlock);
 
157
        if (dep->qflgs & ERTS_DE_QFLG_BUSY)
 
158
            failure = ERTS_DSIG_PREP_WOULD_SUSPEND;
 
159
        erts_smp_spin_unlock(&dep->qlock);
 
160
        if (failure == ERTS_DSIG_PREP_WOULD_SUSPEND)
 
161
            goto fail;
 
162
    }
 
163
    dsdp->proc = proc;
 
164
    dsdp->dep = dep;
 
165
    dsdp->cid = dep->cid;
 
166
    dsdp->connection_id = dep->connection_id;
 
167
    dsdp->no_suspend = no_suspend;
 
168
    if (dspl == ERTS_DSP_NO_LOCK)
 
169
        erts_smp_de_runlock(dep);
 
170
    return ERTS_DSIG_PREP_CONNECTED;
 
171
 
 
172
 fail:
 
173
    if (dspl == ERTS_DSP_RWLOCK)
 
174
        erts_smp_de_rwunlock(dep);
 
175
    else
 
176
        erts_smp_de_runlock(dep);
 
177
    return failure;
 
178
 
 
179
}
 
180
 
 
181
ERTS_GLB_INLINE
 
182
void erts_schedule_dist_command(Port *prt, DistEntry *dist_entry)
 
183
{
 
184
    DistEntry *dep;
 
185
    Eterm id;
 
186
 
 
187
    if (prt) {
 
188
        ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
 
189
        ASSERT((erts_port_status_get(prt) & ERTS_PORT_SFLGS_DEAD) == 0);
 
190
        ASSERT(prt->dist_entry);
 
191
 
 
192
        dep = prt->dist_entry;
 
193
        id = prt->id;
 
194
    }
 
195
    else {
 
196
        ASSERT(dist_entry);
 
197
        ERTS_SMP_LC_ASSERT(erts_lc_rwmtx_is_rlocked(&dist_entry->rwmtx)
 
198
                           || erts_lc_rwmtx_is_rwlocked(&dist_entry->rwmtx));
 
199
        ASSERT(is_internal_port(dist_entry->cid));
 
200
 
 
201
        dep = dist_entry;
 
202
        id = dep->cid;
 
203
    }
 
204
 
 
205
    if (!erts_smp_atomic_xchg(&dep->dist_cmd_scheduled, 1)) {
 
206
        (void) erts_port_task_schedule(id,
 
207
                                       &dep->dist_cmd,
 
208
                                       ERTS_PORT_TASK_DIST_CMD,
 
209
                                       (ErlDrvEvent) -1,
 
210
                                       NULL);
 
211
    }
 
212
}
 
213
 
 
214
#endif
 
215
 
 
216
typedef struct {
 
217
    ErtsLink *d_lnk;
 
218
    ErtsLink *d_sub_lnk;
 
219
} ErtsDistLinkData;
 
220
 
 
221
ERTS_GLB_INLINE void erts_remove_dist_link(ErtsDistLinkData *,
 
222
                                           Eterm,
 
223
                                           Eterm,
 
224
                                           DistEntry *);
 
225
ERTS_GLB_INLINE int erts_was_dist_link_removed(ErtsDistLinkData *);
 
226
ERTS_GLB_INLINE void erts_destroy_dist_link(ErtsDistLinkData *);
 
227
 
 
228
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
 
229
 
 
230
ERTS_GLB_INLINE void
 
231
erts_remove_dist_link(ErtsDistLinkData *dldp,
 
232
                      Eterm lid,
 
233
                      Eterm rid,
 
234
                      DistEntry *dep)
 
235
{
 
236
    erts_smp_de_links_lock(dep);
 
237
    dldp->d_lnk = erts_lookup_link(dep->nlinks, lid);
 
238
    if (!dldp->d_lnk)
 
239
        dldp->d_sub_lnk = NULL;
 
240
    else {
 
241
        dldp->d_sub_lnk = erts_remove_link(&ERTS_LINK_ROOT(dldp->d_lnk), rid);
 
242
        dldp->d_lnk = (ERTS_LINK_ROOT(dldp->d_lnk)
 
243
                       ? NULL
 
244
                       : erts_remove_link(&dep->nlinks, lid));
 
245
    }
 
246
    erts_smp_de_links_unlock(dep);
 
247
}
 
248
 
 
249
ERTS_GLB_INLINE int
 
250
erts_was_dist_link_removed(ErtsDistLinkData *dldp)
 
251
{
 
252
    return dldp->d_sub_lnk != NULL;
 
253
}
 
254
 
 
255
ERTS_GLB_INLINE void
 
256
erts_destroy_dist_link(ErtsDistLinkData *dldp)
 
257
{
 
258
    if (dldp->d_lnk)
 
259
        erts_destroy_link(dldp->d_lnk);
 
260
    if (dldp->d_sub_lnk)
 
261
        erts_destroy_link(dldp->d_sub_lnk);     
 
262
}
 
263
 
 
264
#endif
 
265
 
 
266
/*
 
267
 * erts_dsig_send_* return values.
 
268
 */
 
269
#define ERTS_DSIG_SEND_OK       0
 
270
#define ERTS_DSIG_SEND_YIELD    1
 
271
 
 
272
extern int erts_dsig_send_link(ErtsDSigData *, Eterm, Eterm);
 
273
extern int erts_dsig_send_msg(ErtsDSigData *, Eterm, Eterm);
 
274
extern int erts_dsig_send_exit_tt(ErtsDSigData *, Eterm, Eterm, Eterm, Eterm);
 
275
extern int erts_dsig_send_unlink(ErtsDSigData *, Eterm, Eterm);
 
276
extern int erts_dsig_send_reg_msg(ErtsDSigData *, Eterm, Eterm);
 
277
extern int erts_dsig_send_group_leader(ErtsDSigData *, Eterm, Eterm);
 
278
extern int erts_dsig_send_exit(ErtsDSigData *, Eterm, Eterm, Eterm);
 
279
extern int erts_dsig_send_exit2(ErtsDSigData *, Eterm, Eterm, Eterm);
 
280
extern int erts_dsig_send_demonitor(ErtsDSigData *, Eterm, Eterm, Eterm, int);
 
281
extern int erts_dsig_send_monitor(ErtsDSigData *, Eterm, Eterm, Eterm);
 
282
extern int erts_dsig_send_m_exit(ErtsDSigData *, Eterm, Eterm, Eterm, Eterm);
 
283
 
 
284
extern int erts_dist_command(Port *prt, int reds);
 
285
extern void erts_dist_port_not_busy(Port *prt);
 
286
extern void erts_kill_dist_connection(DistEntry *dep, Uint32);
134
287
 
135
288
extern Uint erts_dist_cache_size(void);
136
 
extern int erts_is_alive(void);
137
289
 
138
290
#endif